From 229a5d9e0bf99f9c6f741f654f1dbe0a7f975872 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 8 Aug 2020 13:39:49 -0400 Subject: Make DisplayPreferencesManager scoped --- .../Users/DisplayPreferencesManager.cs | 36 +++++++--------------- 1 file changed, 11 insertions(+), 25 deletions(-) (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs b/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs index 7c5c5a3ec5..46f1c618f2 100644 --- a/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs +++ b/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs @@ -14,22 +14,21 @@ namespace Jellyfin.Server.Implementations.Users /// public class DisplayPreferencesManager : IDisplayPreferencesManager { - private readonly JellyfinDbProvider _dbProvider; + private readonly JellyfinDb _dbContext; /// /// Initializes a new instance of the class. /// - /// The Jellyfin db provider. - public DisplayPreferencesManager(JellyfinDbProvider dbProvider) + /// The database context. + public DisplayPreferencesManager(JellyfinDb dbContext) { - _dbProvider = dbProvider; + _dbContext = dbContext; } /// public DisplayPreferences GetDisplayPreferences(Guid userId, string client) { - using var dbContext = _dbProvider.CreateContext(); - var prefs = dbContext.DisplayPreferences + var prefs = _dbContext.DisplayPreferences .Include(pref => pref.HomeSections) .FirstOrDefault(pref => pref.UserId == userId && string.Equals(pref.Client, client)); @@ -37,7 +36,7 @@ namespace Jellyfin.Server.Implementations.Users if (prefs == null) { prefs = new DisplayPreferences(userId, client); - dbContext.DisplayPreferences.Add(prefs); + _dbContext.DisplayPreferences.Add(prefs); } return prefs; @@ -46,14 +45,13 @@ namespace Jellyfin.Server.Implementations.Users /// public ItemDisplayPreferences GetItemDisplayPreferences(Guid userId, Guid itemId, string client) { - using var dbContext = _dbProvider.CreateContext(); - var prefs = dbContext.ItemDisplayPreferences + var prefs = _dbContext.ItemDisplayPreferences .FirstOrDefault(pref => pref.UserId == userId && pref.ItemId == itemId && string.Equals(pref.Client, client)); if (prefs == null) { prefs = new ItemDisplayPreferences(userId, Guid.Empty, client); - dbContext.ItemDisplayPreferences.Add(prefs); + _dbContext.ItemDisplayPreferences.Add(prefs); } return prefs; @@ -62,27 +60,15 @@ namespace Jellyfin.Server.Implementations.Users /// public IList ListItemDisplayPreferences(Guid userId, string client) { - using var dbContext = _dbProvider.CreateContext(); - - return dbContext.ItemDisplayPreferences + return _dbContext.ItemDisplayPreferences .Where(prefs => prefs.UserId == userId && prefs.ItemId != Guid.Empty && string.Equals(prefs.Client, client)) .ToList(); } /// - public void SaveChanges(DisplayPreferences preferences) - { - using var dbContext = _dbProvider.CreateContext(); - dbContext.Update(preferences); - dbContext.SaveChanges(); - } - - /// - public void SaveChanges(ItemDisplayPreferences preferences) + public void SaveChanges() { - using var dbContext = _dbProvider.CreateContext(); - dbContext.Update(preferences); - dbContext.SaveChanges(); + _dbContext.SaveChanges(); } } } -- cgit v1.2.3 From 6709645ec910051ca6427c38836548b4ce164d87 Mon Sep 17 00:00:00 2001 From: crobibero Date: Wed, 12 Aug 2020 15:52:29 -0600 Subject: bump deps --- Emby.Server.Implementations/Emby.Server.Implementations.csproj | 8 ++++---- Jellyfin.Api/Jellyfin.Api.csproj | 4 ++-- Jellyfin.Data/Jellyfin.Data.csproj | 4 ++-- .../Jellyfin.Server.Implementations.csproj | 4 ++-- Jellyfin.Server/Jellyfin.Server.csproj | 4 ++-- MediaBrowser.Common/MediaBrowser.Common.csproj | 4 ++-- MediaBrowser.Controller/MediaBrowser.Controller.csproj | 4 ++-- MediaBrowser.Model/MediaBrowser.Model.csproj | 2 +- MediaBrowser.Providers/MediaBrowser.Providers.csproj | 4 ++-- tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 8 ++++---- tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj | 2 +- tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj | 2 +- .../Jellyfin.MediaEncoding.Tests.csproj | 2 +- tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj | 2 +- .../Jellyfin.Server.Implementations.Tests.csproj | 4 ++-- tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj | 4 ++-- 16 files changed, 31 insertions(+), 31 deletions(-) (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 1adef68aa7..3245c0c8b0 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -32,10 +32,10 @@ - - - - + + + + diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 24bc07b666..ca0542b036 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -14,9 +14,9 @@ - + - + diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index 8ce0f3848c..367d147697 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -19,8 +19,8 @@ - - + + diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index 21748ca192..30ed3e6af3 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -24,11 +24,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 7541707d9f..5e85ff4f15 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -41,8 +41,8 @@ - - + + diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 7380f39fda..e0e271e3e3 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -17,8 +17,8 @@ - - + + diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 67f17f7a52..da474fcab8 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -13,8 +13,8 @@ - - + + diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 902e29b20b..4de9329821 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -23,7 +23,7 @@ - + diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 7c0b542509..e2a9172d8f 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -16,8 +16,8 @@ - - + + diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index f77eba376b..4118594ca3 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -14,12 +14,12 @@ - - - + + + - + diff --git a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj index 7464740445..cc802ccdeb 100644 --- a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj +++ b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj index 1559f70ab3..25459287c8 100644 --- a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj +++ b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj index e1a0895476..c43323abc2 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj +++ b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj @@ -21,7 +21,7 @@ - + diff --git a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj index 0e9e915632..d305a10a87 100644 --- a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj +++ b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj index 03187f4b9c..2f47d5ffe2 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj +++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj @@ -15,10 +15,10 @@ - + - + diff --git a/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj b/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj index a4ef10648b..0fea965d2b 100644 --- a/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj +++ b/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj @@ -8,10 +8,10 @@ - + - + -- cgit v1.2.3 From 3e5fe04427d60261bb87df2e124ce7b2e066b88e Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Thu, 13 Aug 2020 20:31:26 -0400 Subject: Migrate ActivityLogEntryPoint.OnPlaybackStart to IEventConsumer --- .../Activity/ActivityLogEntryPoint.cs | 53 ----------- .../Consumers/Session/PlaybackStartLogger.cs | 105 +++++++++++++++++++++ .../Library/PlaybackStartEventArgs.cs | 6 ++ 3 files changed, 111 insertions(+), 53 deletions(-) create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStartLogger.cs create mode 100644 MediaBrowser.Controller/Library/PlaybackStartEventArgs.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index 84bec92014..53b3a6293b 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.Linq; using System.Text; using System.Threading.Tasks; using Jellyfin.Data.Entities; @@ -83,7 +82,6 @@ namespace Emby.Server.Implementations.Activity _sessionManager.AuthenticationFailed += OnAuthenticationFailed; _sessionManager.AuthenticationSucceeded += OnAuthenticationSucceeded; _sessionManager.SessionEnded += OnSessionEnded; - _sessionManager.PlaybackStart += OnPlaybackStart; _sessionManager.PlaybackStopped += OnPlaybackStopped; _subManager.SubtitleDownloadFailure += OnSubtitleDownloadFailure; @@ -161,41 +159,6 @@ namespace Emby.Server.Implementations.Activity .ConfigureAwait(false); } - private async void OnPlaybackStart(object sender, PlaybackProgressEventArgs e) - { - var item = e.MediaInfo; - - if (item == null) - { - _logger.LogWarning("PlaybackStart reported with null media info."); - return; - } - - if (e.Item != null && e.Item.IsThemeMedia) - { - // Don't report theme song or local trailer playback - return; - } - - if (e.Users.Count == 0) - { - return; - } - - var user = e.Users.First(); - - await CreateLogEntry(new ActivityLog( - string.Format( - CultureInfo.InvariantCulture, - _localization.GetLocalizedString("UserStartedPlayingItemWithValues"), - user.Username, - GetItemName(item), - e.DeviceName), - GetPlaybackNotificationType(item.MediaType), - user.Id)) - .ConfigureAwait(false); - } - private static string GetItemName(BaseItemDto item) { var name = item.Name; @@ -213,21 +176,6 @@ namespace Emby.Server.Implementations.Activity return name; } - private static string GetPlaybackNotificationType(string mediaType) - { - if (string.Equals(mediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase)) - { - return NotificationType.AudioPlayback.ToString(); - } - - if (string.Equals(mediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase)) - { - return NotificationType.VideoPlayback.ToString(); - } - - return null; - } - private static string GetPlaybackStoppedNotificationType(string mediaType) { if (string.Equals(mediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase)) @@ -494,7 +442,6 @@ namespace Emby.Server.Implementations.Activity _sessionManager.AuthenticationSucceeded -= OnAuthenticationSucceeded; _sessionManager.SessionEnded -= OnSessionEnded; - _sessionManager.PlaybackStart -= OnPlaybackStart; _sessionManager.PlaybackStopped -= OnPlaybackStopped; _subManager.SubtitleDownloadFailure -= OnSubtitleDownloadFailure; diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStartLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStartLogger.cs new file mode 100644 index 0000000000..c48683ea38 --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStartLogger.cs @@ -0,0 +1,105 @@ +using System; +using System.Globalization; +using System.Linq; +using System.Threading.Tasks; +using Jellyfin.Data.Entities; +using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.Notifications; +using Microsoft.Extensions.Logging; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Session +{ + /// + /// Creates an entry in the activity log whenever a user starts playback. + /// + public class PlaybackStartLogger : IEventConsumer + { + private readonly ILogger _logger; + private readonly ILocalizationManager _localizationManager; + private readonly IActivityManager _activityManager; + + /// + /// Initializes a new instance of the class. + /// + /// The logger. + /// The localization manager. + /// The activity manager. + public PlaybackStartLogger(ILogger logger, ILocalizationManager localizationManager, IActivityManager activityManager) + { + _logger = logger; + _localizationManager = localizationManager; + _activityManager = activityManager; + } + + /// + public async Task OnEvent(PlaybackStartEventArgs eventArgs) + { + if (eventArgs.MediaInfo == null) + { + _logger.LogWarning("PlaybackStart reported with null media info."); + return; + } + + if (eventArgs.Item != null && eventArgs.Item.IsThemeMedia) + { + // Don't report theme song or local trailer playback + return; + } + + if (eventArgs.Users.Count == 0) + { + return; + } + + var user = eventArgs.Users.First(); + + await _activityManager.CreateAsync(new ActivityLog( + string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("UserStartedPlayingItemWithValues"), + user.Username, + GetItemName(eventArgs.MediaInfo), + eventArgs.DeviceName), + GetPlaybackNotificationType(eventArgs.MediaInfo.MediaType), + user.Id)) + .ConfigureAwait(false); + } + + private static string GetItemName(BaseItemDto item) + { + var name = item.Name; + + if (!string.IsNullOrEmpty(item.SeriesName)) + { + name = item.SeriesName + " - " + name; + } + + if (item.Artists != null && item.Artists.Count > 0) + { + name = item.Artists[0] + " - " + name; + } + + return name; + } + + private static string GetPlaybackNotificationType(string mediaType) + { + if (string.Equals(mediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase)) + { + return NotificationType.AudioPlayback.ToString(); + } + + if (string.Equals(mediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase)) + { + return NotificationType.VideoPlayback.ToString(); + } + + return null; + } + } +} diff --git a/MediaBrowser.Controller/Library/PlaybackStartEventArgs.cs b/MediaBrowser.Controller/Library/PlaybackStartEventArgs.cs new file mode 100644 index 0000000000..3aa9c28954 --- /dev/null +++ b/MediaBrowser.Controller/Library/PlaybackStartEventArgs.cs @@ -0,0 +1,6 @@ +namespace MediaBrowser.Controller.Library +{ + public class PlaybackStartEventArgs : PlaybackProgressEventArgs + { + } +} -- cgit v1.2.3 From 5c29b8982d3277ad7456e96331ac6fddbe7e390c Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Thu, 13 Aug 2020 20:33:16 -0400 Subject: Migrate ActivityLogEntryPoint.OnPlaybackStopped to IEventConsumer --- .../Activity/ActivityLogEntryPoint.cs | 76 --------------- .../Events/Consumers/Session/PlaybackStopLogger.cs | 106 +++++++++++++++++++++ 2 files changed, 106 insertions(+), 76 deletions(-) create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStopLogger.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index 53b3a6293b..00910c8a23 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -12,8 +12,6 @@ using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Subtitles; using MediaBrowser.Model.Activity; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; using MediaBrowser.Model.Events; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Notifications; @@ -28,7 +26,6 @@ namespace Emby.Server.Implementations.Activity /// public sealed class ActivityLogEntryPoint : IServerEntryPoint { - private readonly ILogger _logger; private readonly IInstallationManager _installationManager; private readonly ISessionManager _sessionManager; private readonly ITaskManager _taskManager; @@ -40,7 +37,6 @@ namespace Emby.Server.Implementations.Activity /// /// Initializes a new instance of the class. /// - /// The logger. /// The session manager. /// The task manager. /// The activity manager. @@ -49,7 +45,6 @@ namespace Emby.Server.Implementations.Activity /// The subtitle manager. /// The user manager. public ActivityLogEntryPoint( - ILogger logger, ISessionManager sessionManager, ITaskManager taskManager, IActivityManager activityManager, @@ -58,7 +53,6 @@ namespace Emby.Server.Implementations.Activity ISubtitleManager subManager, IUserManager userManager) { - _logger = logger; _sessionManager = sessionManager; _taskManager = taskManager; _activityManager = activityManager; @@ -82,7 +76,6 @@ namespace Emby.Server.Implementations.Activity _sessionManager.AuthenticationFailed += OnAuthenticationFailed; _sessionManager.AuthenticationSucceeded += OnAuthenticationSucceeded; _sessionManager.SessionEnded += OnSessionEnded; - _sessionManager.PlaybackStopped += OnPlaybackStopped; _subManager.SubtitleDownloadFailure += OnSubtitleDownloadFailure; @@ -124,73 +117,6 @@ namespace Emby.Server.Implementations.Activity }).ConfigureAwait(false); } - private async void OnPlaybackStopped(object sender, PlaybackStopEventArgs e) - { - var item = e.MediaInfo; - - if (item == null) - { - _logger.LogWarning("PlaybackStopped reported with null media info."); - return; - } - - if (e.Item != null && e.Item.IsThemeMedia) - { - // Don't report theme song or local trailer playback - return; - } - - if (e.Users.Count == 0) - { - return; - } - - var user = e.Users[0]; - - await CreateLogEntry(new ActivityLog( - string.Format( - CultureInfo.InvariantCulture, - _localization.GetLocalizedString("UserStoppedPlayingItemWithValues"), - user.Username, - GetItemName(item), - e.DeviceName), - GetPlaybackStoppedNotificationType(item.MediaType), - user.Id)) - .ConfigureAwait(false); - } - - private static string GetItemName(BaseItemDto item) - { - var name = item.Name; - - if (!string.IsNullOrEmpty(item.SeriesName)) - { - name = item.SeriesName + " - " + name; - } - - if (item.Artists != null && item.Artists.Count > 0) - { - name = item.Artists[0] + " - " + name; - } - - return name; - } - - private static string GetPlaybackStoppedNotificationType(string mediaType) - { - if (string.Equals(mediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase)) - { - return NotificationType.AudioPlaybackStopped.ToString(); - } - - if (string.Equals(mediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase)) - { - return NotificationType.VideoPlaybackStopped.ToString(); - } - - return null; - } - private async void OnSessionEnded(object sender, SessionEventArgs e) { var session = e.SessionInfo; @@ -442,8 +368,6 @@ namespace Emby.Server.Implementations.Activity _sessionManager.AuthenticationSucceeded -= OnAuthenticationSucceeded; _sessionManager.SessionEnded -= OnSessionEnded; - _sessionManager.PlaybackStopped -= OnPlaybackStopped; - _subManager.SubtitleDownloadFailure -= OnSubtitleDownloadFailure; _userManager.OnUserCreated -= OnUserCreated; diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStopLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStopLogger.cs new file mode 100644 index 0000000000..51a882c143 --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStopLogger.cs @@ -0,0 +1,106 @@ +using System; +using System.Globalization; +using System.Threading.Tasks; +using Jellyfin.Data.Entities; +using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.Notifications; +using Microsoft.Extensions.Logging; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Session +{ + /// + /// Creates an activity log entry whenever a user stops playback. + /// + public class PlaybackStopLogger : IEventConsumer + { + private readonly ILogger _logger; + private readonly ILocalizationManager _localizationManager; + private readonly IActivityManager _activityManager; + + /// + /// Initializes a new instance of the class. + /// + /// The logger. + /// The localization manager. + /// The activity manager. + public PlaybackStopLogger(ILogger logger, ILocalizationManager localizationManager, IActivityManager activityManager) + { + _logger = logger; + _localizationManager = localizationManager; + _activityManager = activityManager; + } + + /// + public async Task OnEvent(PlaybackStopEventArgs eventArgs) + { + var item = eventArgs.MediaInfo; + + if (item == null) + { + _logger.LogWarning("PlaybackStopped reported with null media info."); + return; + } + + if (eventArgs.Item != null && eventArgs.Item.IsThemeMedia) + { + // Don't report theme song or local trailer playback + return; + } + + if (eventArgs.Users.Count == 0) + { + return; + } + + var user = eventArgs.Users[0]; + + await _activityManager.CreateAsync(new ActivityLog( + string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("UserStoppedPlayingItemWithValues"), + user.Username, + GetItemName(item), + eventArgs.DeviceName), + GetPlaybackStoppedNotificationType(item.MediaType), + user.Id)) + .ConfigureAwait(false); + } + + private static string GetItemName(BaseItemDto item) + { + var name = item.Name; + + if (!string.IsNullOrEmpty(item.SeriesName)) + { + name = item.SeriesName + " - " + name; + } + + if (item.Artists != null && item.Artists.Count > 0) + { + name = item.Artists[0] + " - " + name; + } + + return name; + } + + private static string GetPlaybackStoppedNotificationType(string mediaType) + { + if (string.Equals(mediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase)) + { + return NotificationType.AudioPlaybackStopped.ToString(); + } + + if (string.Equals(mediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase)) + { + return NotificationType.VideoPlaybackStopped.ToString(); + } + + return null; + } + } +} -- cgit v1.2.3 From fdd73f1186ab8f938e1139e814aa2afbd4702a78 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Thu, 13 Aug 2020 20:34:28 -0400 Subject: Migrate ActivityLogEntryPoint.OnTaskCompleted to IEventConsumer --- .../Activity/ActivityLogEntryPoint.cs | 136 ------------------ .../Events/Consumers/TaskCompletedLogger.cs | 152 +++++++++++++++++++++ 2 files changed, 152 insertions(+), 136 deletions(-) create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/TaskCompletedLogger.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index 00910c8a23..79d7e17115 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Globalization; -using System.Text; using System.Threading.Tasks; using Jellyfin.Data.Entities; using MediaBrowser.Common.Plugins; @@ -15,7 +13,6 @@ using MediaBrowser.Model.Activity; using MediaBrowser.Model.Events; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Notifications; -using MediaBrowser.Model.Tasks; using MediaBrowser.Model.Updates; using Microsoft.Extensions.Logging; @@ -28,7 +25,6 @@ namespace Emby.Server.Implementations.Activity { private readonly IInstallationManager _installationManager; private readonly ISessionManager _sessionManager; - private readonly ITaskManager _taskManager; private readonly IActivityManager _activityManager; private readonly ILocalizationManager _localization; private readonly ISubtitleManager _subManager; @@ -38,7 +34,6 @@ namespace Emby.Server.Implementations.Activity /// Initializes a new instance of the class. /// /// The session manager. - /// The task manager. /// The activity manager. /// The localization manager. /// The installation manager. @@ -46,7 +41,6 @@ namespace Emby.Server.Implementations.Activity /// The user manager. public ActivityLogEntryPoint( ISessionManager sessionManager, - ITaskManager taskManager, IActivityManager activityManager, ILocalizationManager localization, IInstallationManager installationManager, @@ -54,7 +48,6 @@ namespace Emby.Server.Implementations.Activity IUserManager userManager) { _sessionManager = sessionManager; - _taskManager = taskManager; _activityManager = activityManager; _localization = localization; _installationManager = installationManager; @@ -65,8 +58,6 @@ namespace Emby.Server.Implementations.Activity /// public Task RunAsync() { - _taskManager.TaskCompleted += OnTaskCompleted; - _installationManager.PluginInstalled += OnPluginInstalled; _installationManager.PluginUninstalled += OnPluginUninstalled; _installationManager.PluginUpdated += OnPluginUpdated; @@ -307,57 +298,12 @@ namespace Emby.Server.Implementations.Activity }).ConfigureAwait(false); } - private async void OnTaskCompleted(object sender, TaskCompletionEventArgs e) - { - var result = e.Result; - var task = e.Task; - - if (task.ScheduledTask is IConfigurableScheduledTask activityTask - && !activityTask.IsLogged) - { - return; - } - - var time = result.EndTimeUtc - result.StartTimeUtc; - var runningTime = string.Format( - CultureInfo.InvariantCulture, - _localization.GetLocalizedString("LabelRunningTimeValue"), - ToUserFriendlyString(time)); - - if (result.Status == TaskCompletionStatus.Failed) - { - var vals = new List(); - - if (!string.IsNullOrEmpty(e.Result.ErrorMessage)) - { - vals.Add(e.Result.ErrorMessage); - } - - if (!string.IsNullOrEmpty(e.Result.LongErrorMessage)) - { - vals.Add(e.Result.LongErrorMessage); - } - - await CreateLogEntry(new ActivityLog( - string.Format(CultureInfo.InvariantCulture, _localization.GetLocalizedString("ScheduledTaskFailedWithName"), task.Name), - NotificationType.TaskFailed.ToString(), - Guid.Empty) - { - LogSeverity = LogLevel.Error, - Overview = string.Join(Environment.NewLine, vals), - ShortOverview = runningTime - }).ConfigureAwait(false); - } - } - private async Task CreateLogEntry(ActivityLog entry) => await _activityManager.CreateAsync(entry).ConfigureAwait(false); /// public void Dispose() { - _taskManager.TaskCompleted -= OnTaskCompleted; - _installationManager.PluginInstalled -= OnPluginInstalled; _installationManager.PluginUninstalled -= OnPluginUninstalled; _installationManager.PluginUpdated -= OnPluginUpdated; @@ -375,87 +321,5 @@ namespace Emby.Server.Implementations.Activity _userManager.OnUserDeleted -= OnUserDeleted; _userManager.OnUserLockedOut -= OnUserLockedOut; } - - /// - /// Constructs a user-friendly string for this TimeSpan instance. - /// - private static string ToUserFriendlyString(TimeSpan span) - { - const int DaysInYear = 365; - const int DaysInMonth = 30; - - // Get each non-zero value from TimeSpan component - var values = new List(); - - // Number of years - int days = span.Days; - if (days >= DaysInYear) - { - int years = days / DaysInYear; - values.Add(CreateValueString(years, "year")); - days %= DaysInYear; - } - - // Number of months - if (days >= DaysInMonth) - { - int months = days / DaysInMonth; - values.Add(CreateValueString(months, "month")); - days = days % DaysInMonth; - } - - // Number of days - if (days >= 1) - { - values.Add(CreateValueString(days, "day")); - } - - // Number of hours - if (span.Hours >= 1) - { - values.Add(CreateValueString(span.Hours, "hour")); - } - - // Number of minutes - if (span.Minutes >= 1) - { - values.Add(CreateValueString(span.Minutes, "minute")); - } - - // Number of seconds (include when 0 if no other components included) - if (span.Seconds >= 1 || values.Count == 0) - { - values.Add(CreateValueString(span.Seconds, "second")); - } - - // Combine values into string - var builder = new StringBuilder(); - for (int i = 0; i < values.Count; i++) - { - if (builder.Length > 0) - { - builder.Append(i == values.Count - 1 ? " and " : ", "); - } - - builder.Append(values[i]); - } - - // Return result - return builder.ToString(); - } - - /// - /// Constructs a string description of a time-span value. - /// - /// The value of this item. - /// The name of this item (singular form). - private static string CreateValueString(int value, string description) - { - return string.Format( - CultureInfo.InvariantCulture, - "{0:#,##0} {1}", - value, - value == 1 ? description : string.Format(CultureInfo.InvariantCulture, "{0}s", description)); - } } } diff --git a/Jellyfin.Server.Implementations/Events/Consumers/TaskCompletedLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/TaskCompletedLogger.cs new file mode 100644 index 0000000000..faca66ffd2 --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/TaskCompletedLogger.cs @@ -0,0 +1,152 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; +using System.Threading.Tasks; +using Jellyfin.Data.Entities; +using MediaBrowser.Controller.Events; +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.Notifications; +using MediaBrowser.Model.Tasks; +using Microsoft.Extensions.Logging; + +namespace Jellyfin.Server.Implementations.Events.Consumers +{ + /// + /// Creates an activity log entry whenever a task is completed. + /// + public class TaskCompletedLogger : IEventConsumer + { + private readonly ILocalizationManager _localizationManager; + private readonly IActivityManager _activityManager; + + public TaskCompletedLogger(ILocalizationManager localizationManager, IActivityManager activityManager) + { + _localizationManager = localizationManager; + _activityManager = activityManager; + } + + public async Task OnEvent(TaskCompletionEventArgs e) + { + var result = e.Result; + var task = e.Task; + + if (task.ScheduledTask is IConfigurableScheduledTask activityTask + && !activityTask.IsLogged) + { + return; + } + + var time = result.EndTimeUtc - result.StartTimeUtc; + var runningTime = string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("LabelRunningTimeValue"), + ToUserFriendlyString(time)); + + if (result.Status == TaskCompletionStatus.Failed) + { + var vals = new List(); + + if (!string.IsNullOrEmpty(e.Result.ErrorMessage)) + { + vals.Add(e.Result.ErrorMessage); + } + + if (!string.IsNullOrEmpty(e.Result.LongErrorMessage)) + { + vals.Add(e.Result.LongErrorMessage); + } + + await _activityManager.CreateAsync(new ActivityLog( + string.Format(CultureInfo.InvariantCulture, _localizationManager.GetLocalizedString("ScheduledTaskFailedWithName"), task.Name), + NotificationType.TaskFailed.ToString(), + Guid.Empty) + { + LogSeverity = LogLevel.Error, + Overview = string.Join(Environment.NewLine, vals), + ShortOverview = runningTime + }).ConfigureAwait(false); + } + } + + private static string ToUserFriendlyString(TimeSpan span) + { + const int DaysInYear = 365; + const int DaysInMonth = 30; + + // Get each non-zero value from TimeSpan component + var values = new List(); + + // Number of years + int days = span.Days; + if (days >= DaysInYear) + { + int years = days / DaysInYear; + values.Add(CreateValueString(years, "year")); + days %= DaysInYear; + } + + // Number of months + if (days >= DaysInMonth) + { + int months = days / DaysInMonth; + values.Add(CreateValueString(months, "month")); + days = days % DaysInMonth; + } + + // Number of days + if (days >= 1) + { + values.Add(CreateValueString(days, "day")); + } + + // Number of hours + if (span.Hours >= 1) + { + values.Add(CreateValueString(span.Hours, "hour")); + } + + // Number of minutes + if (span.Minutes >= 1) + { + values.Add(CreateValueString(span.Minutes, "minute")); + } + + // Number of seconds (include when 0 if no other components included) + if (span.Seconds >= 1 || values.Count == 0) + { + values.Add(CreateValueString(span.Seconds, "second")); + } + + // Combine values into string + var builder = new StringBuilder(); + for (int i = 0; i < values.Count; i++) + { + if (builder.Length > 0) + { + builder.Append(i == values.Count - 1 ? " and " : ", "); + } + + builder.Append(values[i]); + } + + // Return result + return builder.ToString(); + } + + /// + /// Constructs a string description of a time-span value. + /// + /// The value of this item. + /// The name of this item (singular form). + private static string CreateValueString(int value, string description) + { + return string.Format( + CultureInfo.InvariantCulture, + "{0:#,##0} {1}", + value, + value == 1 ? description : string.Format(CultureInfo.InvariantCulture, "{0}s", description)); + } + } +} -- cgit v1.2.3 From ade40a4c428ecfab53507fdb6df5ac541f10f3ad Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Thu, 13 Aug 2020 20:40:18 -0400 Subject: Migrate ActivityLogEntryPoint.OnSubtitleDownloadFailure to IEventConsumer --- .../Activity/ActivityLogEntryPoint.cs | 25 ----- .../Library/SubtitleDownloadFailureLogger.cs | 102 +++++++++++++++++++++ 2 files changed, 102 insertions(+), 25 deletions(-) create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Library/SubtitleDownloadFailureLogger.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index 79d7e17115..39b6361b7c 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -8,7 +8,6 @@ using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; -using MediaBrowser.Controller.Subtitles; using MediaBrowser.Model.Activity; using MediaBrowser.Model.Events; using MediaBrowser.Model.Globalization; @@ -27,7 +26,6 @@ namespace Emby.Server.Implementations.Activity private readonly ISessionManager _sessionManager; private readonly IActivityManager _activityManager; private readonly ILocalizationManager _localization; - private readonly ISubtitleManager _subManager; private readonly IUserManager _userManager; /// @@ -37,21 +35,18 @@ namespace Emby.Server.Implementations.Activity /// The activity manager. /// The localization manager. /// The installation manager. - /// The subtitle manager. /// The user manager. public ActivityLogEntryPoint( ISessionManager sessionManager, IActivityManager activityManager, ILocalizationManager localization, IInstallationManager installationManager, - ISubtitleManager subManager, IUserManager userManager) { _sessionManager = sessionManager; _activityManager = activityManager; _localization = localization; _installationManager = installationManager; - _subManager = subManager; _userManager = userManager; } @@ -68,8 +63,6 @@ namespace Emby.Server.Implementations.Activity _sessionManager.AuthenticationSucceeded += OnAuthenticationSucceeded; _sessionManager.SessionEnded += OnSessionEnded; - _subManager.SubtitleDownloadFailure += OnSubtitleDownloadFailure; - _userManager.OnUserCreated += OnUserCreated; _userManager.OnUserPasswordChanged += OnUserPasswordChanged; _userManager.OnUserDeleted += OnUserDeleted; @@ -92,22 +85,6 @@ namespace Emby.Server.Implementations.Activity }).ConfigureAwait(false); } - private async void OnSubtitleDownloadFailure(object sender, SubtitleDownloadFailureEventArgs e) - { - await CreateLogEntry(new ActivityLog( - string.Format( - CultureInfo.InvariantCulture, - _localization.GetLocalizedString("SubtitleDownloadFailureFromForItem"), - e.Provider, - Notifications.NotificationEntryPoint.GetItemName(e.Item)), - "SubtitleDownloadFailure", - Guid.Empty) - { - ItemId = e.Item.Id.ToString("N", CultureInfo.InvariantCulture), - ShortOverview = e.Exception.Message - }).ConfigureAwait(false); - } - private async void OnSessionEnded(object sender, SessionEventArgs e) { var session = e.SessionInfo; @@ -314,8 +291,6 @@ namespace Emby.Server.Implementations.Activity _sessionManager.AuthenticationSucceeded -= OnAuthenticationSucceeded; _sessionManager.SessionEnded -= OnSessionEnded; - _subManager.SubtitleDownloadFailure -= OnSubtitleDownloadFailure; - _userManager.OnUserCreated -= OnUserCreated; _userManager.OnUserPasswordChanged -= OnUserPasswordChanged; _userManager.OnUserDeleted -= OnUserDeleted; diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Library/SubtitleDownloadFailureLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Library/SubtitleDownloadFailureLogger.cs new file mode 100644 index 0000000000..449f27be2c --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Library/SubtitleDownloadFailureLogger.cs @@ -0,0 +1,102 @@ +using System; +using System.Globalization; +using System.Threading.Tasks; +using Jellyfin.Data.Entities; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Subtitles; +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Globalization; +using Episode = MediaBrowser.Controller.Entities.TV.Episode; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Library +{ + /// + /// Creates an entry in the activity log whenever a subtitle download fails. + /// + public class SubtitleDownloadFailureLogger : IEventConsumer + { + private readonly ILocalizationManager _localizationManager; + private readonly IActivityManager _activityManager; + + /// + /// Initializes a new instance of the class. + /// + /// The localization manager. + /// The activity manager. + public SubtitleDownloadFailureLogger(ILocalizationManager localizationManager, IActivityManager activityManager) + { + _localizationManager = localizationManager; + _activityManager = activityManager; + } + + /// + public async Task OnEvent(SubtitleDownloadFailureEventArgs eventArgs) + { + await _activityManager.CreateAsync(new ActivityLog( + string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("SubtitleDownloadFailureFromForItem"), + eventArgs.Provider, + GetItemName(eventArgs.Item)), + "SubtitleDownloadFailure", + Guid.Empty) + { + ItemId = eventArgs.Item.Id.ToString("N", CultureInfo.InvariantCulture), + ShortOverview = eventArgs.Exception.Message + }).ConfigureAwait(false); + } + + private static string GetItemName(BaseItem item) + { + var name = item.Name; + if (item is Episode episode) + { + if (episode.IndexNumber.HasValue) + { + name = string.Format( + CultureInfo.InvariantCulture, + "Ep{0} - {1}", + episode.IndexNumber.Value, + name); + } + + if (episode.ParentIndexNumber.HasValue) + { + name = string.Format( + CultureInfo.InvariantCulture, + "S{0}, {1}", + episode.ParentIndexNumber.Value, + name); + } + } + + if (item is IHasSeries hasSeries) + { + name = hasSeries.SeriesName + " - " + name; + } + + if (item is IHasAlbumArtist hasAlbumArtist) + { + var artists = hasAlbumArtist.AlbumArtists; + + if (artists.Count > 0) + { + name = artists[0] + " - " + name; + } + } + else if (item is IHasArtist hasArtist) + { + var artists = hasArtist.Artists; + + if (artists.Count > 0) + { + name = artists[0] + " - " + name; + } + } + + return name; + } + } +} -- cgit v1.2.3 From ca1f15af19e26f8f610a7b56cd6b15a6a308a58f Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Thu, 13 Aug 2020 20:48:28 -0400 Subject: Move GenericEventArgs to Jellyfin.Data.Events --- Emby.Dlna/PlayTo/PlayToController.cs | 2 +- Emby.Dlna/PlayTo/PlayToManager.cs | 2 +- Emby.Dlna/Ssdp/DeviceDiscovery.cs | 2 +- Emby.Notifications/NotificationEntryPoint.cs | 2 +- .../Activity/ActivityLogEntryPoint.cs | 2 +- .../Configuration/ServerConfigurationManager.cs | 2 +- .../Devices/DeviceManager.cs | 2 +- .../EntryPoints/ExternalPortForwarding.cs | 2 +- .../EntryPoints/LibraryChangedNotifier.cs | 2 +- .../EntryPoints/RecordingNotifier.cs | 9 ++++---- .../EntryPoints/ServerEventNotifier.cs | 2 +- .../HttpServer/HttpListenerHost.cs | 2 +- .../LiveTv/EmbyTV/EmbyTV.cs | 2 +- .../LiveTv/EmbyTV/TimerManager.cs | 2 +- .../LiveTv/LiveTvManager.cs | 2 +- .../ScheduledTasks/ScheduledTaskWorker.cs | 3 +-- .../ScheduledTasks/TaskManager.cs | 2 +- .../Session/SessionManager.cs | 2 +- .../Session/SessionWebSocketListener.cs | 2 +- .../ActivityLogWebSocketListener.cs | 2 +- .../ScheduledTasksWebSocketListener.cs | 2 +- Jellyfin.Data/Events/GenericEventArgs.cs | 26 ++++++++++++++++++++++ .../Activity/ActivityManager.cs | 2 +- .../Users/DeviceAccessEntryPoint.cs | 2 +- .../Users/UserManager.cs | 2 +- MediaBrowser.Controller/Devices/IDeviceManager.cs | 2 +- MediaBrowser.Controller/Library/IUserManager.cs | 2 +- MediaBrowser.Controller/LiveTv/ILiveTvManager.cs | 2 +- MediaBrowser.Controller/Net/IHttpServer.cs | 2 +- .../Providers/IProviderManager.cs | 2 +- MediaBrowser.Controller/Session/ISessionManager.cs | 2 +- MediaBrowser.Model/Activity/IActivityManager.cs | 2 +- MediaBrowser.Model/Dlna/IDeviceDiscovery.cs | 2 +- MediaBrowser.Model/Events/GenericEventArgs.cs | 26 ---------------------- MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs | 2 +- MediaBrowser.Model/Tasks/ITaskManager.cs | 2 +- MediaBrowser.Providers/Manager/ProviderManager.cs | 2 +- 37 files changed, 65 insertions(+), 65 deletions(-) create mode 100644 Jellyfin.Data/Events/GenericEventArgs.cs delete mode 100644 MediaBrowser.Model/Events/GenericEventArgs.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs index 92a93d4349..1f0da8d753 100644 --- a/Emby.Dlna/PlayTo/PlayToController.cs +++ b/Emby.Dlna/PlayTo/PlayToController.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using Emby.Dlna.Didl; using Jellyfin.Data.Entities; +using Jellyfin.Data.Events; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Drawing; @@ -18,7 +19,6 @@ using MediaBrowser.Controller.Session; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Events; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Session; using Microsoft.AspNetCore.WebUtilities; diff --git a/Emby.Dlna/PlayTo/PlayToManager.cs b/Emby.Dlna/PlayTo/PlayToManager.cs index 512589e4d7..00edff1a65 100644 --- a/Emby.Dlna/PlayTo/PlayToManager.cs +++ b/Emby.Dlna/PlayTo/PlayToManager.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Net; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Data.Events; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller; @@ -16,7 +17,6 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Events; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Session; using Microsoft.Extensions.Logging; diff --git a/Emby.Dlna/Ssdp/DeviceDiscovery.cs b/Emby.Dlna/Ssdp/DeviceDiscovery.cs index 7daac96d1d..18ee188fd0 100644 --- a/Emby.Dlna/Ssdp/DeviceDiscovery.cs +++ b/Emby.Dlna/Ssdp/DeviceDiscovery.cs @@ -3,9 +3,9 @@ using System; using System.Collections.Generic; using System.Linq; +using Jellyfin.Data.Events; using MediaBrowser.Controller.Configuration; using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Events; using Rssdp; using Rssdp.Infrastructure; diff --git a/Emby.Notifications/NotificationEntryPoint.cs b/Emby.Notifications/NotificationEntryPoint.cs index b923fd26ce..ded22d26cc 100644 --- a/Emby.Notifications/NotificationEntryPoint.cs +++ b/Emby.Notifications/NotificationEntryPoint.cs @@ -4,6 +4,7 @@ using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Data.Events; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller; using MediaBrowser.Controller.Entities; @@ -13,7 +14,6 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Notifications; using MediaBrowser.Controller.Plugins; using MediaBrowser.Model.Activity; -using MediaBrowser.Model.Events; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Notifications; using Microsoft.Extensions.Logging; diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index 39b6361b7c..75a7916869 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -2,6 +2,7 @@ using System; using System.Globalization; using System.Threading.Tasks; using Jellyfin.Data.Entities; +using Jellyfin.Data.Events; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; using MediaBrowser.Controller.Authentication; @@ -9,7 +10,6 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Activity; -using MediaBrowser.Model.Events; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Notifications; using MediaBrowser.Model.Updates; diff --git a/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs b/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs index a15295fca4..f05a30a897 100644 --- a/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs +++ b/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs @@ -2,11 +2,11 @@ using System; using System.Globalization; using System.IO; using Emby.Server.Implementations.AppBase; +using Jellyfin.Data.Events; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Events; using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; using Microsoft.Extensions.Logging; diff --git a/Emby.Server.Implementations/Devices/DeviceManager.cs b/Emby.Server.Implementations/Devices/DeviceManager.cs index cc4b407f5c..f98c694c46 100644 --- a/Emby.Server.Implementations/Devices/DeviceManager.cs +++ b/Emby.Server.Implementations/Devices/DeviceManager.cs @@ -7,13 +7,13 @@ using System.IO; using System.Linq; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; +using Jellyfin.Data.Events; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Security; using MediaBrowser.Model.Devices; -using MediaBrowser.Model.Events; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Session; diff --git a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index 9fce49425e..2e8cc76d23 100644 --- a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -7,11 +7,11 @@ using System.Net; using System.Text; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Data.Events; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Plugins; using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Events; using Microsoft.Extensions.Logging; using Mono.Nat; diff --git a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs index 1deef7f720..c9d21d9638 100644 --- a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Entities; +using Jellyfin.Data.Events; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; @@ -15,7 +16,6 @@ using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Events; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.EntryPoints diff --git a/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs b/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs index 6327359106..44d2580d68 100644 --- a/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Enums; +using Jellyfin.Data.Events; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Plugins; @@ -43,22 +44,22 @@ namespace Emby.Server.Implementations.EntryPoints return Task.CompletedTask; } - private async void OnLiveTvManagerSeriesTimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs e) + private async void OnLiveTvManagerSeriesTimerCreated(object sender, GenericEventArgs e) { await SendMessage("SeriesTimerCreated", e.Argument).ConfigureAwait(false); } - private async void OnLiveTvManagerTimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs e) + private async void OnLiveTvManagerTimerCreated(object sender, GenericEventArgs e) { await SendMessage("TimerCreated", e.Argument).ConfigureAwait(false); } - private async void OnLiveTvManagerSeriesTimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs e) + private async void OnLiveTvManagerSeriesTimerCancelled(object sender, GenericEventArgs e) { await SendMessage("SeriesTimerCancelled", e.Argument).ConfigureAwait(false); } - private async void OnLiveTvManagerTimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs e) + private async void OnLiveTvManagerTimerCancelled(object sender, GenericEventArgs e) { await SendMessage("TimerCancelled", e.Argument).ConfigureAwait(false); } diff --git a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs index 826d4d8dc3..d023591e19 100644 --- a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs @@ -4,13 +4,13 @@ using System.Globalization; using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Entities; +using Jellyfin.Data.Events; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; using MediaBrowser.Controller; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Events; using MediaBrowser.Model.Tasks; using MediaBrowser.Model.Updates; diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs index dafdd5b7bf..fe39bb4b29 100644 --- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -12,13 +12,13 @@ using System.Threading; using System.Threading.Tasks; using Emby.Server.Implementations.Services; using Emby.Server.Implementations.SocketSharp; +using Jellyfin.Data.Events; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Net; -using MediaBrowser.Model.Events; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Services; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 80e09f0a34..09c52d95bb 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -13,6 +13,7 @@ using System.Threading.Tasks; using System.Xml; using Emby.Server.Implementations.Library; using Jellyfin.Data.Enums; +using Jellyfin.Data.Events; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; @@ -29,7 +30,6 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Events; using MediaBrowser.Model.IO; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.MediaInfo; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs index 285a59a249..dd479b7d1b 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs @@ -5,8 +5,8 @@ using System.Collections.Concurrent; using System.Globalization; using System.Linq; using System.Threading; +using Jellyfin.Data.Events; using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.Events; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Serialization; using Microsoft.Extensions.Logging; diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 1b075d86a8..ef505c78e6 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using Emby.Server.Implementations.Library; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; +using Jellyfin.Data.Events; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Progress; @@ -24,7 +25,6 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Events; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.LiveTv; diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 8a900f42cd..36faae65d2 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -6,11 +6,10 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Data.Events; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Progress; -using MediaBrowser.Model.Events; -using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Tasks; using Microsoft.Extensions.Logging; diff --git a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs index 81096026bd..fff52ff88a 100644 --- a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs +++ b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs @@ -5,8 +5,8 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Jellyfin.Data.Events; using MediaBrowser.Common.Configuration; -using MediaBrowser.Model.Events; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Tasks; using Microsoft.Extensions.Logging; diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 862a7296ca..6e41244639 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -9,6 +9,7 @@ using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; +using Jellyfin.Data.Events; using MediaBrowser.Common.Events; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller; @@ -24,7 +25,6 @@ using MediaBrowser.Controller.Session; using MediaBrowser.Model.Devices; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Events; using MediaBrowser.Model.Library; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Session; diff --git a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs index 8bebd37dc8..1da7a64730 100644 --- a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs +++ b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs @@ -4,9 +4,9 @@ using System.Linq; using System.Net.WebSockets; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Data.Events; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Events; using MediaBrowser.Model.Net; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; diff --git a/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs index 6395b8d62f..849b3b7095 100644 --- a/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs +++ b/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs @@ -1,8 +1,8 @@ using System; using System.Threading.Tasks; +using Jellyfin.Data.Events; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Activity; -using MediaBrowser.Model.Events; using Microsoft.Extensions.Logging; namespace Jellyfin.Api.WebSocketListeners diff --git a/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs index 12f815ff75..8a966c1376 100644 --- a/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs +++ b/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Jellyfin.Data.Events; using MediaBrowser.Controller.Net; -using MediaBrowser.Model.Events; using MediaBrowser.Model.Tasks; using Microsoft.Extensions.Logging; diff --git a/Jellyfin.Data/Events/GenericEventArgs.cs b/Jellyfin.Data/Events/GenericEventArgs.cs new file mode 100644 index 0000000000..7b9a5111ee --- /dev/null +++ b/Jellyfin.Data/Events/GenericEventArgs.cs @@ -0,0 +1,26 @@ +using System; + +namespace Jellyfin.Data.Events +{ + /// + /// Provides a generic EventArgs subclass that can hold any kind of object. + /// + /// The type of this event. + public class GenericEventArgs : EventArgs + { + /// + /// Initializes a new instance of the class. + /// + /// The argument. + public GenericEventArgs(T arg) + { + Argument = arg; + } + + /// + /// Gets the argument. + /// + /// The argument. + public T Argument { get; } + } +} diff --git a/Jellyfin.Server.Implementations/Activity/ActivityManager.cs b/Jellyfin.Server.Implementations/Activity/ActivityManager.cs index 2deefbe819..09f2611e4e 100644 --- a/Jellyfin.Server.Implementations/Activity/ActivityManager.cs +++ b/Jellyfin.Server.Implementations/Activity/ActivityManager.cs @@ -2,8 +2,8 @@ using System; using System.Linq; using System.Threading.Tasks; using Jellyfin.Data.Entities; +using Jellyfin.Data.Events; using MediaBrowser.Model.Activity; -using MediaBrowser.Model.Events; using MediaBrowser.Model.Querying; namespace Jellyfin.Server.Implementations.Activity diff --git a/Jellyfin.Server.Implementations/Users/DeviceAccessEntryPoint.cs b/Jellyfin.Server.Implementations/Users/DeviceAccessEntryPoint.cs index 140853e529..1fb89c4a63 100644 --- a/Jellyfin.Server.Implementations/Users/DeviceAccessEntryPoint.cs +++ b/Jellyfin.Server.Implementations/Users/DeviceAccessEntryPoint.cs @@ -4,12 +4,12 @@ using System.Threading.Tasks; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; +using Jellyfin.Data.Events; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Events; namespace Jellyfin.Server.Implementations.Users { diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index 11402ee055..267c1c1033 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -10,6 +10,7 @@ using System.Text.RegularExpressions; using System.Threading.Tasks; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; +using Jellyfin.Data.Events; using MediaBrowser.Common; using MediaBrowser.Common.Cryptography; using MediaBrowser.Common.Extensions; @@ -21,7 +22,6 @@ using MediaBrowser.Controller.Net; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Cryptography; using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Events; using MediaBrowser.Model.Users; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; diff --git a/MediaBrowser.Controller/Devices/IDeviceManager.cs b/MediaBrowser.Controller/Devices/IDeviceManager.cs index 7d279230b5..a038d84d81 100644 --- a/MediaBrowser.Controller/Devices/IDeviceManager.cs +++ b/MediaBrowser.Controller/Devices/IDeviceManager.cs @@ -1,7 +1,7 @@ using System; using Jellyfin.Data.Entities; +using Jellyfin.Data.Events; using MediaBrowser.Model.Devices; -using MediaBrowser.Model.Events; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Session; diff --git a/MediaBrowser.Controller/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs index 6685861a9a..c8d8375b38 100644 --- a/MediaBrowser.Controller/Library/IUserManager.cs +++ b/MediaBrowser.Controller/Library/IUserManager.cs @@ -2,9 +2,9 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; using Jellyfin.Data.Entities; +using Jellyfin.Data.Events; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Events; using MediaBrowser.Model.Users; namespace MediaBrowser.Controller.Library diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index f619b011bf..d6f629a1b9 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -3,11 +3,11 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Entities; +using Jellyfin.Data.Events; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Events; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Querying; diff --git a/MediaBrowser.Controller/Net/IHttpServer.cs b/MediaBrowser.Controller/Net/IHttpServer.cs index e6609fae38..b04ebda8ca 100644 --- a/MediaBrowser.Controller/Net/IHttpServer.cs +++ b/MediaBrowser.Controller/Net/IHttpServer.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using MediaBrowser.Model.Events; +using Jellyfin.Data.Events; using MediaBrowser.Model.Services; using Microsoft.AspNetCore.Http; diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs index 955db0278c..ef744ee3c1 100644 --- a/MediaBrowser.Controller/Providers/IProviderManager.cs +++ b/MediaBrowser.Controller/Providers/IProviderManager.cs @@ -4,12 +4,12 @@ using System.IO; using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Entities; +using Jellyfin.Data.Events; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Events; using MediaBrowser.Model.Providers; namespace MediaBrowser.Controller.Providers diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index e54f210506..d461a9281a 100644 --- a/MediaBrowser.Controller/Session/ISessionManager.cs +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -2,11 +2,11 @@ using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Data.Events; using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Security; using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Events; using MediaBrowser.Model.Session; using MediaBrowser.Model.SyncPlay; diff --git a/MediaBrowser.Model/Activity/IActivityManager.cs b/MediaBrowser.Model/Activity/IActivityManager.cs index 9dab5e77b7..2362f7e927 100644 --- a/MediaBrowser.Model/Activity/IActivityManager.cs +++ b/MediaBrowser.Model/Activity/IActivityManager.cs @@ -4,7 +4,7 @@ using System; using System.Linq; using System.Threading.Tasks; using Jellyfin.Data.Entities; -using MediaBrowser.Model.Events; +using Jellyfin.Data.Events; using MediaBrowser.Model.Querying; namespace MediaBrowser.Model.Activity diff --git a/MediaBrowser.Model/Dlna/IDeviceDiscovery.cs b/MediaBrowser.Model/Dlna/IDeviceDiscovery.cs index 76c9a4b044..05209e53d0 100644 --- a/MediaBrowser.Model/Dlna/IDeviceDiscovery.cs +++ b/MediaBrowser.Model/Dlna/IDeviceDiscovery.cs @@ -1,7 +1,7 @@ #pragma warning disable CS1591 using System; -using MediaBrowser.Model.Events; +using Jellyfin.Data.Events; namespace MediaBrowser.Model.Dlna { diff --git a/MediaBrowser.Model/Events/GenericEventArgs.cs b/MediaBrowser.Model/Events/GenericEventArgs.cs deleted file mode 100644 index 347ea2281e..0000000000 --- a/MediaBrowser.Model/Events/GenericEventArgs.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; - -namespace MediaBrowser.Model.Events -{ - /// - /// Provides a generic EventArgs subclass that can hold any kind of object. - /// - /// The type of this event. - public class GenericEventArgs : EventArgs - { - /// - /// Initializes a new instance of the class. - /// - /// The argument. - public GenericEventArgs(T arg) - { - Argument = arg; - } - - /// - /// Gets the argument. - /// - /// The argument. - public T Argument { get; } - } -} diff --git a/MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs b/MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs index b08acba2c6..2f05e08c51 100644 --- a/MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs +++ b/MediaBrowser.Model/Tasks/IScheduledTaskWorker.cs @@ -1,6 +1,6 @@ #nullable disable using System; -using MediaBrowser.Model.Events; +using Jellyfin.Data.Events; namespace MediaBrowser.Model.Tasks { diff --git a/MediaBrowser.Model/Tasks/ITaskManager.cs b/MediaBrowser.Model/Tasks/ITaskManager.cs index 363773ff74..02b29074e3 100644 --- a/MediaBrowser.Model/Tasks/ITaskManager.cs +++ b/MediaBrowser.Model/Tasks/ITaskManager.cs @@ -3,7 +3,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using MediaBrowser.Model.Events; +using Jellyfin.Data.Events; namespace MediaBrowser.Model.Tasks { diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index bbd7166e68..9f63c60465 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -9,6 +9,7 @@ using System.Net.Mime; using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Entities; +using Jellyfin.Data.Events; using MediaBrowser.Common.Net; using MediaBrowser.Common.Progress; using MediaBrowser.Controller; @@ -22,7 +23,6 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Subtitles; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Events; using MediaBrowser.Model.IO; using MediaBrowser.Model.Net; using MediaBrowser.Model.Providers; -- cgit v1.2.3 From 18d34f953b4639240b92b373b3f660e87a1e55b5 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Thu, 13 Aug 2020 20:57:13 -0400 Subject: Migrate ActivityLogEntryPoint.OnUserCreated to IEventConsumer --- .../Activity/ActivityLogEntryPoint.cs | 14 ------- Jellyfin.Data/Events/Users/UserCreatedEventArgs.cs | 18 +++++++++ .../Events/Consumers/Users/UserCreatedLogger.cs | 43 ++++++++++++++++++++++ 3 files changed, 61 insertions(+), 14 deletions(-) create mode 100644 Jellyfin.Data/Events/Users/UserCreatedEventArgs.cs create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Users/UserCreatedLogger.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index 75a7916869..b11feff7c7 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -63,7 +63,6 @@ namespace Emby.Server.Implementations.Activity _sessionManager.AuthenticationSucceeded += OnAuthenticationSucceeded; _sessionManager.SessionEnded += OnSessionEnded; - _userManager.OnUserCreated += OnUserCreated; _userManager.OnUserPasswordChanged += OnUserPasswordChanged; _userManager.OnUserDeleted += OnUserDeleted; _userManager.OnUserLockedOut += OnUserLockedOut; @@ -171,18 +170,6 @@ namespace Emby.Server.Implementations.Activity .ConfigureAwait(false); } - private async void OnUserCreated(object sender, GenericEventArgs e) - { - await CreateLogEntry(new ActivityLog( - string.Format( - CultureInfo.InvariantCulture, - _localization.GetLocalizedString("UserCreatedWithName"), - e.Argument.Username), - "UserCreated", - e.Argument.Id)) - .ConfigureAwait(false); - } - private async void OnSessionStarted(object sender, SessionEventArgs e) { var session = e.SessionInfo; @@ -291,7 +278,6 @@ namespace Emby.Server.Implementations.Activity _sessionManager.AuthenticationSucceeded -= OnAuthenticationSucceeded; _sessionManager.SessionEnded -= OnSessionEnded; - _userManager.OnUserCreated -= OnUserCreated; _userManager.OnUserPasswordChanged -= OnUserPasswordChanged; _userManager.OnUserDeleted -= OnUserDeleted; _userManager.OnUserLockedOut -= OnUserLockedOut; diff --git a/Jellyfin.Data/Events/Users/UserCreatedEventArgs.cs b/Jellyfin.Data/Events/Users/UserCreatedEventArgs.cs new file mode 100644 index 0000000000..66f7c8d4fc --- /dev/null +++ b/Jellyfin.Data/Events/Users/UserCreatedEventArgs.cs @@ -0,0 +1,18 @@ +using Jellyfin.Data.Entities; + +namespace Jellyfin.Data.Events.Users +{ + /// + /// An event that occurs when a user is created. + /// + public class UserCreatedEventArgs : GenericEventArgs + { + /// + /// Initializes a new instance of the class. + /// + /// The user. + public UserCreatedEventArgs(User arg) : base(arg) + { + } + } +} diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Users/UserCreatedLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Users/UserCreatedLogger.cs new file mode 100644 index 0000000000..dc855cc368 --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Users/UserCreatedLogger.cs @@ -0,0 +1,43 @@ +using System.Globalization; +using System.Threading.Tasks; +using Jellyfin.Data.Entities; +using Jellyfin.Data.Events.Users; +using MediaBrowser.Controller.Events; +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Globalization; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Users +{ + /// + /// Creates an entry in the activity log when a user is created. + /// + public class UserCreatedLogger : IEventConsumer + { + private readonly ILocalizationManager _localizationManager; + private readonly IActivityManager _activityManager; + + /// + /// Initializes a new instance of the class. + /// + /// The localization manager. + /// The activity manager. + public UserCreatedLogger(ILocalizationManager localizationManager, IActivityManager activityManager) + { + _localizationManager = localizationManager; + _activityManager = activityManager; + } + + /// + public async Task OnEvent(UserCreatedEventArgs eventArgs) + { + await _activityManager.CreateAsync(new ActivityLog( + string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("UserCreatedWithName"), + eventArgs.Argument.Username), + "UserCreated", + eventArgs.Argument.Id)) + .ConfigureAwait(false); + } + } +} -- cgit v1.2.3 From 737a86d0cbd4dfce86bbe25fb7669f74cbde6d0a Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Thu, 13 Aug 2020 21:01:35 -0400 Subject: Migrate ActivityLogEntryPoint.OnUserDeleted to IEventConsumer --- .../Activity/ActivityLogEntryPoint.cs | 14 --------- Jellyfin.Data/Events/Users/UserDeletedEventArgs.cs | 18 +++++++++++ .../Events/Consumers/Users/UserDeletedLogger.cs | 35 ++++++++++++++++++++++ 3 files changed, 53 insertions(+), 14 deletions(-) create mode 100644 Jellyfin.Data/Events/Users/UserDeletedEventArgs.cs create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Users/UserDeletedLogger.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index b11feff7c7..e5ef944311 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -64,7 +64,6 @@ namespace Emby.Server.Implementations.Activity _sessionManager.SessionEnded += OnSessionEnded; _userManager.OnUserPasswordChanged += OnUserPasswordChanged; - _userManager.OnUserDeleted += OnUserDeleted; _userManager.OnUserLockedOut += OnUserLockedOut; return Task.CompletedTask; @@ -146,18 +145,6 @@ namespace Emby.Server.Implementations.Activity }).ConfigureAwait(false); } - private async void OnUserDeleted(object sender, GenericEventArgs e) - { - await CreateLogEntry(new ActivityLog( - string.Format( - CultureInfo.InvariantCulture, - _localization.GetLocalizedString("UserDeletedWithName"), - e.Argument.Username), - "UserDeleted", - Guid.Empty)) - .ConfigureAwait(false); - } - private async void OnUserPasswordChanged(object sender, GenericEventArgs e) { await CreateLogEntry(new ActivityLog( @@ -279,7 +266,6 @@ namespace Emby.Server.Implementations.Activity _sessionManager.SessionEnded -= OnSessionEnded; _userManager.OnUserPasswordChanged -= OnUserPasswordChanged; - _userManager.OnUserDeleted -= OnUserDeleted; _userManager.OnUserLockedOut -= OnUserLockedOut; } } diff --git a/Jellyfin.Data/Events/Users/UserDeletedEventArgs.cs b/Jellyfin.Data/Events/Users/UserDeletedEventArgs.cs new file mode 100644 index 0000000000..0b94933754 --- /dev/null +++ b/Jellyfin.Data/Events/Users/UserDeletedEventArgs.cs @@ -0,0 +1,18 @@ +using Jellyfin.Data.Entities; + +namespace Jellyfin.Data.Events.Users +{ + /// + /// An event that occurs when a user is deleted. + /// + public class UserDeletedEventArgs : GenericEventArgs + { + /// + /// Initializes a new instance of the class. + /// + /// The user. + public UserDeletedEventArgs(User arg) : base(arg) + { + } + } +} diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Users/UserDeletedLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Users/UserDeletedLogger.cs new file mode 100644 index 0000000000..1a3975067c --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Users/UserDeletedLogger.cs @@ -0,0 +1,35 @@ +using System; +using System.Globalization; +using System.Threading.Tasks; +using Jellyfin.Data.Entities; +using Jellyfin.Data.Events.Users; +using MediaBrowser.Controller.Events; +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Globalization; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Users +{ + public class UserDeletedLogger : IEventConsumer + { + private readonly ILocalizationManager _localizationManager; + private readonly IActivityManager _activityManager; + + public UserDeletedLogger(ILocalizationManager localizationManager, IActivityManager activityManager) + { + _localizationManager = localizationManager; + _activityManager = activityManager; + } + + public async Task OnEvent(UserDeletedEventArgs eventArgs) + { + await _activityManager.CreateAsync(new ActivityLog( + string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("UserDeletedWithName"), + eventArgs.Argument.Username), + "UserDeleted", + Guid.Empty)) + .ConfigureAwait(false); + } + } +} -- cgit v1.2.3 From a1ecafb40d8cacb9ea63833ddc311c59d738044c Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Thu, 13 Aug 2020 21:07:08 -0400 Subject: Migrate ActivityLogEntryPoint.OnUserPasswordChanged to IEventConsumer --- .../Activity/ActivityLogEntryPoint.cs | 14 ------- .../Events/Users/UserPasswordChangedEventArgs.cs | 18 +++++++++ .../Consumers/Users/UserPasswordChangedLogger.cs | 43 ++++++++++++++++++++++ 3 files changed, 61 insertions(+), 14 deletions(-) create mode 100644 Jellyfin.Data/Events/Users/UserPasswordChangedEventArgs.cs create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Users/UserPasswordChangedLogger.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index e5ef944311..8fc0b527f0 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -63,7 +63,6 @@ namespace Emby.Server.Implementations.Activity _sessionManager.AuthenticationSucceeded += OnAuthenticationSucceeded; _sessionManager.SessionEnded += OnSessionEnded; - _userManager.OnUserPasswordChanged += OnUserPasswordChanged; _userManager.OnUserLockedOut += OnUserLockedOut; return Task.CompletedTask; @@ -145,18 +144,6 @@ namespace Emby.Server.Implementations.Activity }).ConfigureAwait(false); } - private async void OnUserPasswordChanged(object sender, GenericEventArgs e) - { - await CreateLogEntry(new ActivityLog( - string.Format( - CultureInfo.InvariantCulture, - _localization.GetLocalizedString("UserPasswordChangedWithName"), - e.Argument.Username), - "UserPasswordChanged", - e.Argument.Id)) - .ConfigureAwait(false); - } - private async void OnSessionStarted(object sender, SessionEventArgs e) { var session = e.SessionInfo; @@ -265,7 +252,6 @@ namespace Emby.Server.Implementations.Activity _sessionManager.AuthenticationSucceeded -= OnAuthenticationSucceeded; _sessionManager.SessionEnded -= OnSessionEnded; - _userManager.OnUserPasswordChanged -= OnUserPasswordChanged; _userManager.OnUserLockedOut -= OnUserLockedOut; } } diff --git a/Jellyfin.Data/Events/Users/UserPasswordChangedEventArgs.cs b/Jellyfin.Data/Events/Users/UserPasswordChangedEventArgs.cs new file mode 100644 index 0000000000..087ec9ab68 --- /dev/null +++ b/Jellyfin.Data/Events/Users/UserPasswordChangedEventArgs.cs @@ -0,0 +1,18 @@ +using Jellyfin.Data.Entities; + +namespace Jellyfin.Data.Events.Users +{ + /// + /// An event that occurs when a user's password has changed. + /// + public class UserPasswordChangedEventArgs : GenericEventArgs + { + /// + /// Initializes a new instance of the class. + /// + /// The user. + public UserPasswordChangedEventArgs(User arg) : base(arg) + { + } + } +} diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Users/UserPasswordChangedLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Users/UserPasswordChangedLogger.cs new file mode 100644 index 0000000000..dc8ecbf48f --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Users/UserPasswordChangedLogger.cs @@ -0,0 +1,43 @@ +using System.Globalization; +using System.Threading.Tasks; +using Jellyfin.Data.Entities; +using Jellyfin.Data.Events.Users; +using MediaBrowser.Controller.Events; +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Globalization; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Users +{ + /// + /// Creates an entry in the activity log when a user's password is changed. + /// + public class UserPasswordChangedLogger : IEventConsumer + { + private readonly ILocalizationManager _localizationManager; + private readonly IActivityManager _activityManager; + + /// + /// Initializes a new instance of the class. + /// + /// The localization manager. + /// The activity manager. + public UserPasswordChangedLogger(ILocalizationManager localizationManager, IActivityManager activityManager) + { + _localizationManager = localizationManager; + _activityManager = activityManager; + } + + /// + public async Task OnEvent(UserPasswordChangedEventArgs eventArgs) + { + await _activityManager.CreateAsync(new ActivityLog( + string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("UserPasswordChangedWithName"), + eventArgs.Argument.Username), + "UserPasswordChanged", + eventArgs.Argument.Id)) + .ConfigureAwait(false); + } + } +} -- cgit v1.2.3 From 8a4bdaed6bce53d8ea10dba8a71fb450edd5feca Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Thu, 13 Aug 2020 21:11:38 -0400 Subject: Migrate ActivityLogEntryPoint.OnUserLockedOut to IEventConsumer --- .../Activity/ActivityLogEntryPoint.cs | 25 +----------- .../Events/Users/UserLockedOutEventArgs.cs | 18 +++++++++ .../Events/Consumers/Users/UserLockedOutLogger.cs | 47 ++++++++++++++++++++++ 3 files changed, 66 insertions(+), 24 deletions(-) create mode 100644 Jellyfin.Data/Events/Users/UserLockedOutEventArgs.cs create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Users/UserLockedOutLogger.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index 8fc0b527f0..0000195d86 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -6,7 +6,6 @@ using Jellyfin.Data.Events; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; using MediaBrowser.Controller.Authentication; -using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Activity; @@ -26,7 +25,6 @@ namespace Emby.Server.Implementations.Activity private readonly ISessionManager _sessionManager; private readonly IActivityManager _activityManager; private readonly ILocalizationManager _localization; - private readonly IUserManager _userManager; /// /// Initializes a new instance of the class. @@ -35,19 +33,16 @@ namespace Emby.Server.Implementations.Activity /// The activity manager. /// The localization manager. /// The installation manager. - /// The user manager. public ActivityLogEntryPoint( ISessionManager sessionManager, IActivityManager activityManager, ILocalizationManager localization, - IInstallationManager installationManager, - IUserManager userManager) + IInstallationManager installationManager) { _sessionManager = sessionManager; _activityManager = activityManager; _localization = localization; _installationManager = installationManager; - _userManager = userManager; } /// @@ -63,25 +58,9 @@ namespace Emby.Server.Implementations.Activity _sessionManager.AuthenticationSucceeded += OnAuthenticationSucceeded; _sessionManager.SessionEnded += OnSessionEnded; - _userManager.OnUserLockedOut += OnUserLockedOut; - return Task.CompletedTask; } - private async void OnUserLockedOut(object sender, GenericEventArgs e) - { - await CreateLogEntry(new ActivityLog( - string.Format( - CultureInfo.InvariantCulture, - _localization.GetLocalizedString("UserLockedOutWithName"), - e.Argument.Username), - NotificationType.UserLockedOut.ToString(), - e.Argument.Id) - { - LogSeverity = LogLevel.Error - }).ConfigureAwait(false); - } - private async void OnSessionEnded(object sender, SessionEventArgs e) { var session = e.SessionInfo; @@ -251,8 +230,6 @@ namespace Emby.Server.Implementations.Activity _sessionManager.AuthenticationFailed -= OnAuthenticationFailed; _sessionManager.AuthenticationSucceeded -= OnAuthenticationSucceeded; _sessionManager.SessionEnded -= OnSessionEnded; - - _userManager.OnUserLockedOut -= OnUserLockedOut; } } } diff --git a/Jellyfin.Data/Events/Users/UserLockedOutEventArgs.cs b/Jellyfin.Data/Events/Users/UserLockedOutEventArgs.cs new file mode 100644 index 0000000000..cca3726dc5 --- /dev/null +++ b/Jellyfin.Data/Events/Users/UserLockedOutEventArgs.cs @@ -0,0 +1,18 @@ +using Jellyfin.Data.Entities; + +namespace Jellyfin.Data.Events.Users +{ + /// + /// An event that occurs when a user is locked out. + /// + public class UserLockedOutEventArgs : GenericEventArgs + { + /// + /// Initializes a new instance of the class. + /// + /// The user. + public UserLockedOutEventArgs(User arg) : base(arg) + { + } + } +} diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Users/UserLockedOutLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Users/UserLockedOutLogger.cs new file mode 100644 index 0000000000..a31f222ee7 --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Users/UserLockedOutLogger.cs @@ -0,0 +1,47 @@ +using System.Globalization; +using System.Threading.Tasks; +using Jellyfin.Data.Entities; +using Jellyfin.Data.Events.Users; +using MediaBrowser.Controller.Events; +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.Notifications; +using Microsoft.Extensions.Logging; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Users +{ + /// + /// Creates an entry in the activity log when a user is locked out. + /// + public class UserLockedOutLogger : IEventConsumer + { + private readonly ILocalizationManager _localizationManager; + private readonly IActivityManager _activityManager; + + /// + /// Initializes a new instance of the class. + /// + /// The localization manager. + /// The activity manager. + public UserLockedOutLogger(ILocalizationManager localizationManager, IActivityManager activityManager) + { + _localizationManager = localizationManager; + _activityManager = activityManager; + } + + /// + public async Task OnEvent(UserLockedOutEventArgs eventArgs) + { + await _activityManager.CreateAsync(new ActivityLog( + string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("UserLockedOutWithName"), + eventArgs.Argument.Username), + NotificationType.UserLockedOut.ToString(), + eventArgs.Argument.Id) + { + LogSeverity = LogLevel.Error + }).ConfigureAwait(false); + } + } +} -- cgit v1.2.3 From bff05d71861bd1b82777df3140a6f9dd5599ba98 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Thu, 13 Aug 2020 21:33:28 -0400 Subject: Migrate ActivityLogEntryPoint.OnAuthenticationFailed to IEventConsumer --- .../Activity/ActivityLogEntryPoint.cs | 21 --------- .../Security/AuthenticationFailedLogger.cs | 52 ++++++++++++++++++++++ 2 files changed, 52 insertions(+), 21 deletions(-) create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationFailedLogger.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index 0000195d86..8279503ec8 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -12,7 +12,6 @@ using MediaBrowser.Model.Activity; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Notifications; using MediaBrowser.Model.Updates; -using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.Activity { @@ -54,7 +53,6 @@ namespace Emby.Server.Implementations.Activity _installationManager.PackageInstallationFailed += OnPackageInstallationFailed; _sessionManager.SessionStarted += OnSessionStarted; - _sessionManager.AuthenticationFailed += OnAuthenticationFailed; _sessionManager.AuthenticationSucceeded += OnAuthenticationSucceeded; _sessionManager.SessionEnded += OnSessionEnded; @@ -105,24 +103,6 @@ namespace Emby.Server.Implementations.Activity }).ConfigureAwait(false); } - private async void OnAuthenticationFailed(object sender, GenericEventArgs e) - { - await CreateLogEntry(new ActivityLog( - string.Format( - CultureInfo.InvariantCulture, - _localization.GetLocalizedString("FailedLoginAttemptWithUserName"), - e.Argument.Username), - "AuthenticationFailed", - Guid.Empty) - { - LogSeverity = LogLevel.Error, - ShortOverview = string.Format( - CultureInfo.InvariantCulture, - _localization.GetLocalizedString("LabelIpAddressValue"), - e.Argument.RemoteEndPoint), - }).ConfigureAwait(false); - } - private async void OnSessionStarted(object sender, SessionEventArgs e) { var session = e.SessionInfo; @@ -227,7 +207,6 @@ namespace Emby.Server.Implementations.Activity _installationManager.PackageInstallationFailed -= OnPackageInstallationFailed; _sessionManager.SessionStarted -= OnSessionStarted; - _sessionManager.AuthenticationFailed -= OnAuthenticationFailed; _sessionManager.AuthenticationSucceeded -= OnAuthenticationSucceeded; _sessionManager.SessionEnded -= OnSessionEnded; } diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationFailedLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationFailedLogger.cs new file mode 100644 index 0000000000..f899b4497a --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationFailedLogger.cs @@ -0,0 +1,52 @@ +using System; +using System.Globalization; +using System.Threading.Tasks; +using Jellyfin.Data.Entities; +using Jellyfin.Data.Events; +using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Globalization; +using Microsoft.Extensions.Logging; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Security +{ + /// + /// Creates an entry in the activity log when there is a failed login attempt. + /// + public class AuthenticationFailedLogger : IEventConsumer> + { + private readonly ILocalizationManager _localizationManager; + private readonly IActivityManager _activityManager; + + /// + /// Initializes a new instance of the class. + /// + /// The localization manager. + /// The activity manager. + public AuthenticationFailedLogger(ILocalizationManager localizationManager, IActivityManager activityManager) + { + _localizationManager = localizationManager; + _activityManager = activityManager; + } + + /// + public async Task OnEvent(GenericEventArgs eventArgs) + { + await _activityManager.CreateAsync(new ActivityLog( + string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("FailedLoginAttemptWithUserName"), + eventArgs.Argument.Username), + "AuthenticationFailed", + Guid.Empty) + { + LogSeverity = LogLevel.Error, + ShortOverview = string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("LabelIpAddressValue"), + eventArgs.Argument.RemoteEndPoint), + }).ConfigureAwait(false); + } + } +} -- cgit v1.2.3 From f4275adfcb4c7c5e2daedbad09c64c04fc1ebc53 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Thu, 13 Aug 2020 21:38:24 -0400 Subject: Migrate ActivityLogEntryPoint.OnAuthenticationSucceeded to IEventConsumer --- .../Activity/ActivityLogEntryPoint.cs | 23 ---------- .../Security/AuthenticationSucceededLogger.cs | 49 ++++++++++++++++++++++ 2 files changed, 49 insertions(+), 23 deletions(-) create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationSucceededLogger.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index 8279503ec8..40fc7d8907 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -2,10 +2,8 @@ using System; using System.Globalization; using System.Threading.Tasks; using Jellyfin.Data.Entities; -using Jellyfin.Data.Events; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; -using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Activity; @@ -53,7 +51,6 @@ namespace Emby.Server.Implementations.Activity _installationManager.PackageInstallationFailed += OnPackageInstallationFailed; _sessionManager.SessionStarted += OnSessionStarted; - _sessionManager.AuthenticationSucceeded += OnAuthenticationSucceeded; _sessionManager.SessionEnded += OnSessionEnded; return Task.CompletedTask; @@ -84,25 +81,6 @@ namespace Emby.Server.Implementations.Activity }).ConfigureAwait(false); } - private async void OnAuthenticationSucceeded(object sender, GenericEventArgs e) - { - var user = e.Argument.User; - - await CreateLogEntry(new ActivityLog( - string.Format( - CultureInfo.InvariantCulture, - _localization.GetLocalizedString("AuthenticationSucceededWithUserName"), - user.Name), - "AuthenticationSucceeded", - user.Id) - { - ShortOverview = string.Format( - CultureInfo.InvariantCulture, - _localization.GetLocalizedString("LabelIpAddressValue"), - e.Argument.SessionInfo.RemoteEndPoint), - }).ConfigureAwait(false); - } - private async void OnSessionStarted(object sender, SessionEventArgs e) { var session = e.SessionInfo; @@ -207,7 +185,6 @@ namespace Emby.Server.Implementations.Activity _installationManager.PackageInstallationFailed -= OnPackageInstallationFailed; _sessionManager.SessionStarted -= OnSessionStarted; - _sessionManager.AuthenticationSucceeded -= OnAuthenticationSucceeded; _sessionManager.SessionEnded -= OnSessionEnded; } } diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationSucceededLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationSucceededLogger.cs new file mode 100644 index 0000000000..2f9f44ed67 --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationSucceededLogger.cs @@ -0,0 +1,49 @@ +using System.Globalization; +using System.Threading.Tasks; +using Jellyfin.Data.Entities; +using Jellyfin.Data.Events; +using MediaBrowser.Controller.Authentication; +using MediaBrowser.Controller.Events; +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Globalization; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Security +{ + /// + /// Creates an entry in the activity log when there is a successful login attempt. + /// + public class AuthenticationSucceededLogger : IEventConsumer> + { + private readonly ILocalizationManager _localizationManager; + private readonly IActivityManager _activityManager; + + /// + /// Initializes a new instance of the class. + /// + /// The localization manager. + /// The activity manager. + public AuthenticationSucceededLogger(ILocalizationManager localizationManager, IActivityManager activityManager) + { + _localizationManager = localizationManager; + _activityManager = activityManager; + } + + /// + public async Task OnEvent(GenericEventArgs e) + { + await _activityManager.CreateAsync(new ActivityLog( + string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("AuthenticationSucceededWithUserName"), + e.Argument.User.Name), + "AuthenticationSucceeded", + e.Argument.User.Id) + { + ShortOverview = string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("LabelIpAddressValue"), + e.Argument.SessionInfo.RemoteEndPoint), + }).ConfigureAwait(false); + } + } +} -- cgit v1.2.3 From b7f21971f43d6d9f956ff0aade31625d3995858a Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Fri, 14 Aug 2020 15:21:17 -0400 Subject: Migrate ActivityLogEntryPoint.OnPluginInstalled to IEventConsumer --- .../Activity/ActivityLogEntryPoint.cs | 19 -------- .../Consumers/Updates/PluginInstalledLogger.cs | 50 ++++++++++++++++++++++ .../Events/Updates/PluginInstalledEventArgs.cs | 19 ++++++++ 3 files changed, 69 insertions(+), 19 deletions(-) create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstalledLogger.cs create mode 100644 MediaBrowser.Controller/Events/Updates/PluginInstalledEventArgs.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index 40fc7d8907..600c1d3ea2 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -45,7 +45,6 @@ namespace Emby.Server.Implementations.Activity /// public Task RunAsync() { - _installationManager.PluginInstalled += OnPluginInstalled; _installationManager.PluginUninstalled += OnPluginUninstalled; _installationManager.PluginUpdated += OnPluginUpdated; _installationManager.PackageInstallationFailed += OnPackageInstallationFailed; @@ -136,23 +135,6 @@ namespace Emby.Server.Implementations.Activity .ConfigureAwait(false); } - private async void OnPluginInstalled(object sender, InstallationInfo e) - { - await CreateLogEntry(new ActivityLog( - string.Format( - CultureInfo.InvariantCulture, - _localization.GetLocalizedString("PluginInstalledWithName"), - e.Name), - NotificationType.PluginInstalled.ToString(), - Guid.Empty) - { - ShortOverview = string.Format( - CultureInfo.InvariantCulture, - _localization.GetLocalizedString("VersionNumber"), - e.Version) - }).ConfigureAwait(false); - } - private async void OnPackageInstallationFailed(object sender, InstallationFailedEventArgs e) { var installationInfo = e.InstallationInfo; @@ -179,7 +161,6 @@ namespace Emby.Server.Implementations.Activity /// public void Dispose() { - _installationManager.PluginInstalled -= OnPluginInstalled; _installationManager.PluginUninstalled -= OnPluginUninstalled; _installationManager.PluginUpdated -= OnPluginUpdated; _installationManager.PackageInstallationFailed -= OnPackageInstallationFailed; diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstalledLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstalledLogger.cs new file mode 100644 index 0000000000..8837172dbe --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstalledLogger.cs @@ -0,0 +1,50 @@ +using System; +using System.Globalization; +using System.Threading.Tasks; +using Jellyfin.Data.Entities; +using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Events.Updates; +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.Notifications; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Updates +{ + /// + /// Creates an entry in the activity log when a plugin is installed. + /// + public class PluginInstalledLogger : IEventConsumer + { + private readonly ILocalizationManager _localizationManager; + private readonly IActivityManager _activityManager; + + /// + /// Initializes a new instance of the class. + /// + /// The localization manager. + /// The activity manager. + public PluginInstalledLogger(ILocalizationManager localizationManager, IActivityManager activityManager) + { + _localizationManager = localizationManager; + _activityManager = activityManager; + } + + /// + public async Task OnEvent(PluginInstalledEventArgs eventArgs) + { + await _activityManager.CreateAsync(new ActivityLog( + string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("PluginInstalledWithName"), + eventArgs.Argument.Name), + NotificationType.PluginInstalled.ToString(), + Guid.Empty) + { + ShortOverview = string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("VersionNumber"), + eventArgs.Argument.Version) + }).ConfigureAwait(false); + } + } +} diff --git a/MediaBrowser.Controller/Events/Updates/PluginInstalledEventArgs.cs b/MediaBrowser.Controller/Events/Updates/PluginInstalledEventArgs.cs new file mode 100644 index 0000000000..dfadc9f61f --- /dev/null +++ b/MediaBrowser.Controller/Events/Updates/PluginInstalledEventArgs.cs @@ -0,0 +1,19 @@ +using Jellyfin.Data.Events; +using MediaBrowser.Model.Updates; + +namespace MediaBrowser.Controller.Events.Updates +{ + /// + /// An event that occurs when a plugin is installed. + /// + public class PluginInstalledEventArgs : GenericEventArgs + { + /// + /// Initializes a new instance of the class. + /// + /// The installation info. + public PluginInstalledEventArgs(InstallationInfo arg) : base(arg) + { + } + } +} -- cgit v1.2.3 From 0da7c0568d61e834b8b11693ed79eee2855d4ae6 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Fri, 14 Aug 2020 15:22:12 -0400 Subject: Migrate ActivityLogEntryPoint.OnPluginUninstalled to IEventConsumer --- .../Activity/ActivityLogEntryPoint.cs | 15 -------- .../Consumers/Updates/PluginUninstalledLogger.cs | 45 ++++++++++++++++++++++ .../Events/Updates/PluginUninstalledEventArgs.cs | 19 +++++++++ 3 files changed, 64 insertions(+), 15 deletions(-) create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUninstalledLogger.cs create mode 100644 MediaBrowser.Controller/Events/Updates/PluginUninstalledEventArgs.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index 600c1d3ea2..ba0bf9ea2e 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -2,7 +2,6 @@ using System; using System.Globalization; using System.Threading.Tasks; using Jellyfin.Data.Entities; -using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; @@ -45,7 +44,6 @@ namespace Emby.Server.Implementations.Activity /// public Task RunAsync() { - _installationManager.PluginUninstalled += OnPluginUninstalled; _installationManager.PluginUpdated += OnPluginUpdated; _installationManager.PackageInstallationFailed += OnPackageInstallationFailed; @@ -123,18 +121,6 @@ namespace Emby.Server.Implementations.Activity }).ConfigureAwait(false); } - private async void OnPluginUninstalled(object sender, IPlugin e) - { - await CreateLogEntry(new ActivityLog( - string.Format( - CultureInfo.InvariantCulture, - _localization.GetLocalizedString("PluginUninstalledWithName"), - e.Name), - NotificationType.PluginUninstalled.ToString(), - Guid.Empty)) - .ConfigureAwait(false); - } - private async void OnPackageInstallationFailed(object sender, InstallationFailedEventArgs e) { var installationInfo = e.InstallationInfo; @@ -161,7 +147,6 @@ namespace Emby.Server.Implementations.Activity /// public void Dispose() { - _installationManager.PluginUninstalled -= OnPluginUninstalled; _installationManager.PluginUpdated -= OnPluginUpdated; _installationManager.PackageInstallationFailed -= OnPackageInstallationFailed; diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUninstalledLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUninstalledLogger.cs new file mode 100644 index 0000000000..91a30069e8 --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUninstalledLogger.cs @@ -0,0 +1,45 @@ +using System; +using System.Globalization; +using System.Threading.Tasks; +using Jellyfin.Data.Entities; +using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Events.Updates; +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.Notifications; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Updates +{ + /// + /// Creates an entry in the activity log when a plugin is uninstalled. + /// + public class PluginUninstalledLogger : IEventConsumer + { + private readonly ILocalizationManager _localizationManager; + private readonly IActivityManager _activityManager; + + /// + /// Initializes a new instance of the class. + /// + /// The localization manager. + /// The activity manager. + public PluginUninstalledLogger(ILocalizationManager localizationManager, IActivityManager activityManager) + { + _localizationManager = localizationManager; + _activityManager = activityManager; + } + + /// + public async Task OnEvent(PluginUninstalledEventArgs e) + { + await _activityManager.CreateAsync(new ActivityLog( + string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("PluginUninstalledWithName"), + e.Argument.Name), + NotificationType.PluginUninstalled.ToString(), + Guid.Empty)) + .ConfigureAwait(false); + } + } +} diff --git a/MediaBrowser.Controller/Events/Updates/PluginUninstalledEventArgs.cs b/MediaBrowser.Controller/Events/Updates/PluginUninstalledEventArgs.cs new file mode 100644 index 0000000000..7510b62b88 --- /dev/null +++ b/MediaBrowser.Controller/Events/Updates/PluginUninstalledEventArgs.cs @@ -0,0 +1,19 @@ +using Jellyfin.Data.Events; +using MediaBrowser.Common.Plugins; + +namespace MediaBrowser.Controller.Events.Updates +{ + /// + /// An event that occurs when a plugin is uninstalled. + /// + public class PluginUninstalledEventArgs : GenericEventArgs + { + /// + /// Initializes a new instance of the class. + /// + /// The plugin. + public PluginUninstalledEventArgs(IPlugin arg) : base(arg) + { + } + } +} -- cgit v1.2.3 From e9244448809cb4251b341832c8fdfecde5f169ab Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Fri, 14 Aug 2020 15:50:17 -0400 Subject: Migrate ActivityLogEntryPoint.OnPluginUpdated to IEventConsumer --- .../Activity/ActivityLogEntryPoint.cs | 21 --------- .../Consumers/Updates/PluginUpdatedLogger.cs | 51 ++++++++++++++++++++++ .../Events/Updates/PluginUpdatedEventArgs.cs | 19 ++++++++ 3 files changed, 70 insertions(+), 21 deletions(-) create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUpdatedLogger.cs create mode 100644 MediaBrowser.Controller/Events/Updates/PluginUpdatedEventArgs.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index ba0bf9ea2e..ee058fd468 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -8,7 +8,6 @@ using MediaBrowser.Controller.Session; using MediaBrowser.Model.Activity; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Notifications; -using MediaBrowser.Model.Updates; namespace Emby.Server.Implementations.Activity { @@ -44,7 +43,6 @@ namespace Emby.Server.Implementations.Activity /// public Task RunAsync() { - _installationManager.PluginUpdated += OnPluginUpdated; _installationManager.PackageInstallationFailed += OnPackageInstallationFailed; _sessionManager.SessionStarted += OnSessionStarted; @@ -103,24 +101,6 @@ namespace Emby.Server.Implementations.Activity }).ConfigureAwait(false); } - private async void OnPluginUpdated(object sender, InstallationInfo e) - { - await CreateLogEntry(new ActivityLog( - string.Format( - CultureInfo.InvariantCulture, - _localization.GetLocalizedString("PluginUpdatedWithName"), - e.Name), - NotificationType.PluginUpdateInstalled.ToString(), - Guid.Empty) - { - ShortOverview = string.Format( - CultureInfo.InvariantCulture, - _localization.GetLocalizedString("VersionNumber"), - e.Version), - Overview = e.Changelog - }).ConfigureAwait(false); - } - private async void OnPackageInstallationFailed(object sender, InstallationFailedEventArgs e) { var installationInfo = e.InstallationInfo; @@ -147,7 +127,6 @@ namespace Emby.Server.Implementations.Activity /// public void Dispose() { - _installationManager.PluginUpdated -= OnPluginUpdated; _installationManager.PackageInstallationFailed -= OnPackageInstallationFailed; _sessionManager.SessionStarted -= OnSessionStarted; diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUpdatedLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUpdatedLogger.cs new file mode 100644 index 0000000000..9ce16f774f --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUpdatedLogger.cs @@ -0,0 +1,51 @@ +using System; +using System.Globalization; +using System.Threading.Tasks; +using Jellyfin.Data.Entities; +using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Events.Updates; +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.Notifications; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Updates +{ + /// + /// Creates an entry in the activity log when a plugin is updated. + /// + public class PluginUpdatedLogger : IEventConsumer + { + private readonly ILocalizationManager _localizationManager; + private readonly IActivityManager _activityManager; + + /// + /// Initializes a new instance of the class. + /// + /// The localization manager. + /// The activity manager. + public PluginUpdatedLogger(ILocalizationManager localizationManager, IActivityManager activityManager) + { + _localizationManager = localizationManager; + _activityManager = activityManager; + } + + /// + public async Task OnEvent(PluginUpdatedEventArgs eventArgs) + { + await _activityManager.CreateAsync(new ActivityLog( + string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("PluginUpdatedWithName"), + eventArgs.Argument.Name), + NotificationType.PluginUpdateInstalled.ToString(), + Guid.Empty) + { + ShortOverview = string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("VersionNumber"), + eventArgs.Argument.Version), + Overview = eventArgs.Argument.Changelog + }).ConfigureAwait(false); + } + } +} diff --git a/MediaBrowser.Controller/Events/Updates/PluginUpdatedEventArgs.cs b/MediaBrowser.Controller/Events/Updates/PluginUpdatedEventArgs.cs new file mode 100644 index 0000000000..661ca066a8 --- /dev/null +++ b/MediaBrowser.Controller/Events/Updates/PluginUpdatedEventArgs.cs @@ -0,0 +1,19 @@ +using Jellyfin.Data.Events; +using MediaBrowser.Model.Updates; + +namespace MediaBrowser.Controller.Events.Updates +{ + /// + /// An event that occurs when a plugin is updated. + /// + public class PluginUpdatedEventArgs : GenericEventArgs + { + /// + /// Initializes a new instance of the class. + /// + /// The installation info. + public PluginUpdatedEventArgs(InstallationInfo arg) : base(arg) + { + } + } +} -- cgit v1.2.3 From 98cbf1c2de5151e88977143e415fe4a0b3cad7cf Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Fri, 14 Aug 2020 15:56:54 -0400 Subject: Migrate ActivityLogEntryPoint.OnPackageInstallationFailed to IEventConsumer --- .../Activity/ActivityLogEntryPoint.cs | 33 +------------- .../Updates/PackageInstallationFailedLogger.cs | 51 ++++++++++++++++++++++ .../Updates/InstallationEventArgs.cs | 3 +- 3 files changed, 54 insertions(+), 33 deletions(-) create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Updates/PackageInstallationFailedLogger.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index ee058fd468..00a14fb0bd 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -1,13 +1,10 @@ -using System; using System.Globalization; using System.Threading.Tasks; using Jellyfin.Data.Entities; -using MediaBrowser.Common.Updates; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Activity; using MediaBrowser.Model.Globalization; -using MediaBrowser.Model.Notifications; namespace Emby.Server.Implementations.Activity { @@ -16,7 +13,6 @@ namespace Emby.Server.Implementations.Activity /// public sealed class ActivityLogEntryPoint : IServerEntryPoint { - private readonly IInstallationManager _installationManager; private readonly ISessionManager _sessionManager; private readonly IActivityManager _activityManager; private readonly ILocalizationManager _localization; @@ -27,24 +23,19 @@ namespace Emby.Server.Implementations.Activity /// The session manager. /// The activity manager. /// The localization manager. - /// The installation manager. public ActivityLogEntryPoint( ISessionManager sessionManager, IActivityManager activityManager, - ILocalizationManager localization, - IInstallationManager installationManager) + ILocalizationManager localization) { _sessionManager = sessionManager; _activityManager = activityManager; _localization = localization; - _installationManager = installationManager; } /// public Task RunAsync() { - _installationManager.PackageInstallationFailed += OnPackageInstallationFailed; - _sessionManager.SessionStarted += OnSessionStarted; _sessionManager.SessionEnded += OnSessionEnded; @@ -101,34 +92,12 @@ namespace Emby.Server.Implementations.Activity }).ConfigureAwait(false); } - private async void OnPackageInstallationFailed(object sender, InstallationFailedEventArgs e) - { - var installationInfo = e.InstallationInfo; - - await CreateLogEntry(new ActivityLog( - string.Format( - CultureInfo.InvariantCulture, - _localization.GetLocalizedString("NameInstallFailed"), - installationInfo.Name), - NotificationType.InstallationFailed.ToString(), - Guid.Empty) - { - ShortOverview = string.Format( - CultureInfo.InvariantCulture, - _localization.GetLocalizedString("VersionNumber"), - installationInfo.Version), - Overview = e.Exception.Message - }).ConfigureAwait(false); - } - private async Task CreateLogEntry(ActivityLog entry) => await _activityManager.CreateAsync(entry).ConfigureAwait(false); /// public void Dispose() { - _installationManager.PackageInstallationFailed -= OnPackageInstallationFailed; - _sessionManager.SessionStarted -= OnSessionStarted; _sessionManager.SessionEnded -= OnSessionEnded; } diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PackageInstallationFailedLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PackageInstallationFailedLogger.cs new file mode 100644 index 0000000000..5d7296b3b7 --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PackageInstallationFailedLogger.cs @@ -0,0 +1,51 @@ +using System; +using System.Globalization; +using System.Threading.Tasks; +using Jellyfin.Data.Entities; +using MediaBrowser.Common.Updates; +using MediaBrowser.Controller.Events; +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.Notifications; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Updates +{ + /// + /// Creates an entry in the activity log when a package installation fails. + /// + public class PackageInstallationFailedLogger : IEventConsumer + { + private readonly ILocalizationManager _localizationManager; + private readonly IActivityManager _activityManager; + + /// + /// Initializes a new instance of the class. + /// + /// The localization manager. + /// The activity manager. + public PackageInstallationFailedLogger(ILocalizationManager localizationManager, IActivityManager activityManager) + { + _localizationManager = localizationManager; + _activityManager = activityManager; + } + + /// + public async Task OnEvent(InstallationFailedEventArgs eventArgs) + { + await _activityManager.CreateAsync(new ActivityLog( + string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("NameInstallFailed"), + eventArgs.InstallationInfo.Name), + NotificationType.InstallationFailed.ToString(), + Guid.Empty) + { + ShortOverview = string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("VersionNumber"), + eventArgs.InstallationInfo.Version), + Overview = eventArgs.Exception.Message + }).ConfigureAwait(false); + } + } +} diff --git a/MediaBrowser.Common/Updates/InstallationEventArgs.cs b/MediaBrowser.Common/Updates/InstallationEventArgs.cs index 11eb2ad34a..61178f631c 100644 --- a/MediaBrowser.Common/Updates/InstallationEventArgs.cs +++ b/MediaBrowser.Common/Updates/InstallationEventArgs.cs @@ -1,10 +1,11 @@ #pragma warning disable CS1591 +using System; using MediaBrowser.Model.Updates; namespace MediaBrowser.Common.Updates { - public class InstallationEventArgs + public class InstallationEventArgs : EventArgs { public InstallationInfo InstallationInfo { get; set; } -- cgit v1.2.3 From ca3a8bdb98aeb5d112a4d2a456ebcc445dc5fd12 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 15 Aug 2020 02:02:58 -0400 Subject: Migrate ActivityLogEntryPoint.OnSessionStarted to IEventConsumer --- .../Activity/ActivityLogEntryPoint.cs | 27 ----------- .../Consumers/Session/SessionStartedLogger.cs | 54 ++++++++++++++++++++++ .../Events/Session/SessionStartedEventArgs.cs | 19 ++++++++ 3 files changed, 73 insertions(+), 27 deletions(-) create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Session/SessionStartedLogger.cs create mode 100644 MediaBrowser.Controller/Events/Session/SessionStartedEventArgs.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index 00a14fb0bd..d863acd0b4 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -36,7 +36,6 @@ namespace Emby.Server.Implementations.Activity /// public Task RunAsync() { - _sessionManager.SessionStarted += OnSessionStarted; _sessionManager.SessionEnded += OnSessionEnded; return Task.CompletedTask; @@ -67,38 +66,12 @@ namespace Emby.Server.Implementations.Activity }).ConfigureAwait(false); } - private async void OnSessionStarted(object sender, SessionEventArgs e) - { - var session = e.SessionInfo; - - if (string.IsNullOrEmpty(session.UserName)) - { - return; - } - - await CreateLogEntry(new ActivityLog( - string.Format( - CultureInfo.InvariantCulture, - _localization.GetLocalizedString("UserOnlineFromDevice"), - session.UserName, - session.DeviceName), - "SessionStarted", - session.UserId) - { - ShortOverview = string.Format( - CultureInfo.InvariantCulture, - _localization.GetLocalizedString("LabelIpAddressValue"), - session.RemoteEndPoint) - }).ConfigureAwait(false); - } - private async Task CreateLogEntry(ActivityLog entry) => await _activityManager.CreateAsync(entry).ConfigureAwait(false); /// public void Dispose() { - _sessionManager.SessionStarted -= OnSessionStarted; _sessionManager.SessionEnded -= OnSessionEnded; } } diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Session/SessionStartedLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Session/SessionStartedLogger.cs new file mode 100644 index 0000000000..6a0f29b09f --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Session/SessionStartedLogger.cs @@ -0,0 +1,54 @@ +using System.Globalization; +using System.Threading.Tasks; +using Jellyfin.Data.Entities; +using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Events.Session; +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Globalization; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Session +{ + /// + /// Creates an entry in the activity log when a session is started. + /// + public class SessionStartedLogger : IEventConsumer + { + private readonly ILocalizationManager _localizationManager; + private readonly IActivityManager _activityManager; + + /// + /// Initializes a new instance of the class. + /// + /// The localization manager. + /// The activity manager. + public SessionStartedLogger(ILocalizationManager localizationManager, IActivityManager activityManager) + { + _localizationManager = localizationManager; + _activityManager = activityManager; + } + + /// + public async Task OnEvent(SessionStartedEventArgs eventArgs) + { + if (string.IsNullOrEmpty(eventArgs.Argument.UserName)) + { + return; + } + + await _activityManager.CreateAsync(new ActivityLog( + string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("UserOnlineFromDevice"), + eventArgs.Argument.UserName, + eventArgs.Argument.DeviceName), + "SessionStarted", + eventArgs.Argument.UserId) + { + ShortOverview = string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("LabelIpAddressValue"), + eventArgs.Argument.RemoteEndPoint) + }).ConfigureAwait(false); + } + } +} diff --git a/MediaBrowser.Controller/Events/Session/SessionStartedEventArgs.cs b/MediaBrowser.Controller/Events/Session/SessionStartedEventArgs.cs new file mode 100644 index 0000000000..aab19cc46a --- /dev/null +++ b/MediaBrowser.Controller/Events/Session/SessionStartedEventArgs.cs @@ -0,0 +1,19 @@ +using Jellyfin.Data.Events; +using MediaBrowser.Controller.Session; + +namespace MediaBrowser.Controller.Events.Session +{ + /// + /// An event that fires when a session is started. + /// + public class SessionStartedEventArgs : GenericEventArgs + { + /// + /// Initializes a new instance of the class. + /// + /// The session info. + public SessionStartedEventArgs(SessionInfo arg) : base(arg) + { + } + } +} -- cgit v1.2.3 From 8570cfdba652eb61e2746ea9de6cb9c8bb23eaf5 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 15 Aug 2020 02:07:28 -0400 Subject: Migrate ActivityLogEntryPoint.OnSessionEnded to IEventConsumer --- .../Activity/ActivityLogEntryPoint.cs | 78 ---------------------- .../Consumers/Session/SessionManagerEndedLogger.cs | 54 +++++++++++++++ .../Events/Session/SessionEndedEventArgs.cs | 19 ++++++ 3 files changed, 73 insertions(+), 78 deletions(-) delete mode 100644 Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Session/SessionManagerEndedLogger.cs create mode 100644 MediaBrowser.Controller/Events/Session/SessionEndedEventArgs.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs deleted file mode 100644 index d863acd0b4..0000000000 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System.Globalization; -using System.Threading.Tasks; -using Jellyfin.Data.Entities; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Activity; -using MediaBrowser.Model.Globalization; - -namespace Emby.Server.Implementations.Activity -{ - /// - /// Entry point for the activity logger. - /// - public sealed class ActivityLogEntryPoint : IServerEntryPoint - { - private readonly ISessionManager _sessionManager; - private readonly IActivityManager _activityManager; - private readonly ILocalizationManager _localization; - - /// - /// Initializes a new instance of the class. - /// - /// The session manager. - /// The activity manager. - /// The localization manager. - public ActivityLogEntryPoint( - ISessionManager sessionManager, - IActivityManager activityManager, - ILocalizationManager localization) - { - _sessionManager = sessionManager; - _activityManager = activityManager; - _localization = localization; - } - - /// - public Task RunAsync() - { - _sessionManager.SessionEnded += OnSessionEnded; - - return Task.CompletedTask; - } - - private async void OnSessionEnded(object sender, SessionEventArgs e) - { - var session = e.SessionInfo; - - if (string.IsNullOrEmpty(session.UserName)) - { - return; - } - - await CreateLogEntry(new ActivityLog( - string.Format( - CultureInfo.InvariantCulture, - _localization.GetLocalizedString("UserOfflineFromDevice"), - session.UserName, - session.DeviceName), - "SessionEnded", - session.UserId) - { - ShortOverview = string.Format( - CultureInfo.InvariantCulture, - _localization.GetLocalizedString("LabelIpAddressValue"), - session.RemoteEndPoint), - }).ConfigureAwait(false); - } - - private async Task CreateLogEntry(ActivityLog entry) - => await _activityManager.CreateAsync(entry).ConfigureAwait(false); - - /// - public void Dispose() - { - _sessionManager.SessionEnded -= OnSessionEnded; - } - } -} diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Session/SessionManagerEndedLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Session/SessionManagerEndedLogger.cs new file mode 100644 index 0000000000..1162fe89b7 --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Session/SessionManagerEndedLogger.cs @@ -0,0 +1,54 @@ +using System.Globalization; +using System.Threading.Tasks; +using Jellyfin.Data.Entities; +using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Events.Session; +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Globalization; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Session +{ + /// + /// Creates an entry in the activity log whenever a session ends. + /// + public class SessionManagerEndedLogger : IEventConsumer + { + private readonly ILocalizationManager _localizationManager; + private readonly IActivityManager _activityManager; + + /// + /// Initializes a new instance of the class. + /// + /// The localization manager. + /// The activity manager. + public SessionManagerEndedLogger(ILocalizationManager localizationManager, IActivityManager activityManager) + { + _localizationManager = localizationManager; + _activityManager = activityManager; + } + + /// + public async Task OnEvent(SessionEndedEventArgs eventArgs) + { + if (string.IsNullOrEmpty(eventArgs.Argument.UserName)) + { + return; + } + + await _activityManager.CreateAsync(new ActivityLog( + string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("UserOfflineFromDevice"), + eventArgs.Argument.UserName, + eventArgs.Argument.DeviceName), + "SessionEnded", + eventArgs.Argument.UserId) + { + ShortOverview = string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("LabelIpAddressValue"), + eventArgs.Argument.RemoteEndPoint), + }).ConfigureAwait(false); + } + } +} diff --git a/MediaBrowser.Controller/Events/Session/SessionEndedEventArgs.cs b/MediaBrowser.Controller/Events/Session/SessionEndedEventArgs.cs new file mode 100644 index 0000000000..46d7e5a17a --- /dev/null +++ b/MediaBrowser.Controller/Events/Session/SessionEndedEventArgs.cs @@ -0,0 +1,19 @@ +using Jellyfin.Data.Events; +using MediaBrowser.Controller.Session; + +namespace MediaBrowser.Controller.Events.Session +{ + /// + /// An event that fires when a session is ended. + /// + public class SessionEndedEventArgs : GenericEventArgs + { + /// + /// Initializes a new instance of the class. + /// + /// The session info. + public SessionEndedEventArgs(SessionInfo arg) : base(arg) + { + } + } +} -- cgit v1.2.3 From 665f58dfbd28d455754cf7bdfc2cafcd84464d64 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 15 Aug 2020 03:34:52 -0400 Subject: Document TaskCompletedLogger --- .../Events/Consumers/TaskCompletedLogger.cs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Events/Consumers/TaskCompletedLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/TaskCompletedLogger.cs index faca66ffd2..7f737ee7e6 100644 --- a/Jellyfin.Server.Implementations/Events/Consumers/TaskCompletedLogger.cs +++ b/Jellyfin.Server.Implementations/Events/Consumers/TaskCompletedLogger.cs @@ -21,12 +21,18 @@ namespace Jellyfin.Server.Implementations.Events.Consumers private readonly ILocalizationManager _localizationManager; private readonly IActivityManager _activityManager; + /// + /// Initializes a new instance of the class. + /// + /// The localization manager. + /// The activity manager. public TaskCompletedLogger(ILocalizationManager localizationManager, IActivityManager activityManager) { _localizationManager = localizationManager; _activityManager = activityManager; } + /// public async Task OnEvent(TaskCompletionEventArgs e) { var result = e.Result; -- cgit v1.2.3 From 4d18dbf9de7346c6620a6f9fad7e8f09c13dc68c Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 15 Aug 2020 03:35:42 -0400 Subject: Document UserDeletedLogger --- .../Events/Consumers/Users/UserDeletedLogger.cs | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Users/UserDeletedLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Users/UserDeletedLogger.cs index 1a3975067c..c68a62c812 100644 --- a/Jellyfin.Server.Implementations/Events/Consumers/Users/UserDeletedLogger.cs +++ b/Jellyfin.Server.Implementations/Events/Consumers/Users/UserDeletedLogger.cs @@ -9,17 +9,26 @@ using MediaBrowser.Model.Globalization; namespace Jellyfin.Server.Implementations.Events.Consumers.Users { + /// + /// Adds an entry to the activity log when a user is deleted. + /// public class UserDeletedLogger : IEventConsumer { private readonly ILocalizationManager _localizationManager; private readonly IActivityManager _activityManager; + /// + /// Initializes a new instance of the class. + /// + /// The localization manager. + /// The activity manager. public UserDeletedLogger(ILocalizationManager localizationManager, IActivityManager activityManager) { _localizationManager = localizationManager; _activityManager = activityManager; } + /// public async Task OnEvent(UserDeletedEventArgs eventArgs) { await _activityManager.CreateAsync(new ActivityLog( -- cgit v1.2.3 From 93c00c144046ef9dfd2c9ba47f71e3a45ceade8f Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 15 Aug 2020 13:48:12 -0400 Subject: Rename to SessionEndedLogger --- .../Events/Consumers/Session/SessionEndedLogger.cs | 54 ++++++++++++++++++++++ .../Consumers/Session/SessionManagerEndedLogger.cs | 54 ---------------------- 2 files changed, 54 insertions(+), 54 deletions(-) create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Session/SessionEndedLogger.cs delete mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Session/SessionManagerEndedLogger.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Session/SessionEndedLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Session/SessionEndedLogger.cs new file mode 100644 index 0000000000..cf20946ec9 --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Session/SessionEndedLogger.cs @@ -0,0 +1,54 @@ +using System.Globalization; +using System.Threading.Tasks; +using Jellyfin.Data.Entities; +using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Events.Session; +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Globalization; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Session +{ + /// + /// Creates an entry in the activity log whenever a session ends. + /// + public class SessionEndedLogger : IEventConsumer + { + private readonly ILocalizationManager _localizationManager; + private readonly IActivityManager _activityManager; + + /// + /// Initializes a new instance of the class. + /// + /// The localization manager. + /// The activity manager. + public SessionEndedLogger(ILocalizationManager localizationManager, IActivityManager activityManager) + { + _localizationManager = localizationManager; + _activityManager = activityManager; + } + + /// + public async Task OnEvent(SessionEndedEventArgs eventArgs) + { + if (string.IsNullOrEmpty(eventArgs.Argument.UserName)) + { + return; + } + + await _activityManager.CreateAsync(new ActivityLog( + string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("UserOfflineFromDevice"), + eventArgs.Argument.UserName, + eventArgs.Argument.DeviceName), + "SessionEnded", + eventArgs.Argument.UserId) + { + ShortOverview = string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("LabelIpAddressValue"), + eventArgs.Argument.RemoteEndPoint), + }).ConfigureAwait(false); + } + } +} diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Session/SessionManagerEndedLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Session/SessionManagerEndedLogger.cs deleted file mode 100644 index 1162fe89b7..0000000000 --- a/Jellyfin.Server.Implementations/Events/Consumers/Session/SessionManagerEndedLogger.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.Globalization; -using System.Threading.Tasks; -using Jellyfin.Data.Entities; -using MediaBrowser.Controller.Events; -using MediaBrowser.Controller.Events.Session; -using MediaBrowser.Model.Activity; -using MediaBrowser.Model.Globalization; - -namespace Jellyfin.Server.Implementations.Events.Consumers.Session -{ - /// - /// Creates an entry in the activity log whenever a session ends. - /// - public class SessionManagerEndedLogger : IEventConsumer - { - private readonly ILocalizationManager _localizationManager; - private readonly IActivityManager _activityManager; - - /// - /// Initializes a new instance of the class. - /// - /// The localization manager. - /// The activity manager. - public SessionManagerEndedLogger(ILocalizationManager localizationManager, IActivityManager activityManager) - { - _localizationManager = localizationManager; - _activityManager = activityManager; - } - - /// - public async Task OnEvent(SessionEndedEventArgs eventArgs) - { - if (string.IsNullOrEmpty(eventArgs.Argument.UserName)) - { - return; - } - - await _activityManager.CreateAsync(new ActivityLog( - string.Format( - CultureInfo.InvariantCulture, - _localizationManager.GetLocalizedString("UserOfflineFromDevice"), - eventArgs.Argument.UserName, - eventArgs.Argument.DeviceName), - "SessionEnded", - eventArgs.Argument.UserId) - { - ShortOverview = string.Format( - CultureInfo.InvariantCulture, - _localizationManager.GetLocalizedString("LabelIpAddressValue"), - eventArgs.Argument.RemoteEndPoint), - }).ConfigureAwait(false); - } - } -} -- cgit v1.2.3 From d39e236dfe146de65c2451dfe59abbcc9e8a3b4e Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 15 Aug 2020 15:49:11 -0400 Subject: Migrates ServerEventNotifier.OnUserDeleted to IEventConsumer --- .../EntryPoints/ServerEventNotifier.cs | 13 -------- .../Events/Consumers/Users/UserDeletedNotifier.cs | 38 ++++++++++++++++++++++ 2 files changed, 38 insertions(+), 13 deletions(-) create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Users/UserDeletedNotifier.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs index d023591e19..1ec1f08683 100644 --- a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Entities; @@ -68,7 +67,6 @@ namespace Emby.Server.Implementations.EntryPoints /// public Task RunAsync() { - _userManager.OnUserDeleted += OnUserDeleted; _userManager.OnUserUpdated += OnUserUpdated; _appHost.HasPendingRestartChanged += OnHasPendingRestartChanged; @@ -141,16 +139,6 @@ namespace Emby.Server.Implementations.EntryPoints await SendMessageToUserSession(e.Argument, "UserUpdated", dto).ConfigureAwait(false); } - /// - /// Users the manager_ user deleted. - /// - /// The sender. - /// The e. - private async void OnUserDeleted(object sender, GenericEventArgs e) - { - await SendMessageToUserSession(e.Argument, "UserDeleted", e.Argument.Id.ToString("N", CultureInfo.InvariantCulture)).ConfigureAwait(false); - } - private async Task SendMessageToAdminSessions(string name, T data) { try @@ -192,7 +180,6 @@ namespace Emby.Server.Implementations.EntryPoints { if (dispose) { - _userManager.OnUserDeleted -= OnUserDeleted; _userManager.OnUserUpdated -= OnUserUpdated; _installationManager.PluginUninstalled -= OnPluginUninstalled; diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Users/UserDeletedNotifier.cs b/Jellyfin.Server.Implementations/Events/Consumers/Users/UserDeletedNotifier.cs new file mode 100644 index 0000000000..10367a939b --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Users/UserDeletedNotifier.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Threading; +using System.Threading.Tasks; +using Jellyfin.Data.Events.Users; +using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Session; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Users +{ + /// + /// Notifies the user's sessions when a user is deleted. + /// + public class UserDeletedNotifier : IEventConsumer + { + private readonly ISessionManager _sessionManager; + + /// + /// Initializes a new instance of the class. + /// + /// The session manager. + public UserDeletedNotifier(ISessionManager sessionManager) + { + _sessionManager = sessionManager; + } + + /// + public async Task OnEvent(UserDeletedEventArgs eventArgs) + { + await _sessionManager.SendMessageToUserSessions( + new List { eventArgs.Argument.Id }, + "UserDeleted", + eventArgs.Argument.Id.ToString("N", CultureInfo.InvariantCulture), + CancellationToken.None).ConfigureAwait(false); + } + } +} -- cgit v1.2.3 From 816c80525a64fcac441f44f1d508028070fdc21d Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 15 Aug 2020 15:55:15 -0400 Subject: Use IEventManager in UserManager --- .../Users/UserManager.cs | 29 +++++++++------------- MediaBrowser.Controller/Events/IEventManager.cs | 10 +++++++- MediaBrowser.Controller/Library/IUserManager.cs | 20 --------------- 3 files changed, 21 insertions(+), 38 deletions(-) (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index 267c1c1033..3e8edeb442 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -11,12 +11,14 @@ using System.Threading.Tasks; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; using Jellyfin.Data.Events; +using Jellyfin.Data.Events.Users; using MediaBrowser.Common; using MediaBrowser.Common.Cryptography; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.Drawing; +using MediaBrowser.Controller.Events; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Configuration; @@ -34,6 +36,7 @@ namespace Jellyfin.Server.Implementations.Users public class UserManager : IUserManager { private readonly JellyfinDbProvider _dbProvider; + private readonly IEventManager _eventManager; private readonly ICryptoProvider _cryptoProvider; private readonly INetworkManager _networkManager; private readonly IApplicationHost _appHost; @@ -49,6 +52,7 @@ namespace Jellyfin.Server.Implementations.Users /// Initializes a new instance of the class. /// /// The database provider. + /// The event manager. /// The cryptography provider. /// The network manager. /// The application host. @@ -56,6 +60,7 @@ namespace Jellyfin.Server.Implementations.Users /// The logger. public UserManager( JellyfinDbProvider dbProvider, + IEventManager eventManager, ICryptoProvider cryptoProvider, INetworkManager networkManager, IApplicationHost appHost, @@ -63,6 +68,7 @@ namespace Jellyfin.Server.Implementations.Users ILogger logger) { _dbProvider = dbProvider; + _eventManager = eventManager; _cryptoProvider = cryptoProvider; _networkManager = networkManager; _appHost = appHost; @@ -77,21 +83,9 @@ namespace Jellyfin.Server.Implementations.Users _defaultPasswordResetProvider = _passwordResetProviders.OfType().First(); } - /// - public event EventHandler>? OnUserPasswordChanged; - /// public event EventHandler>? OnUserUpdated; - /// - public event EventHandler>? OnUserCreated; - - /// - public event EventHandler>? OnUserDeleted; - - /// - public event EventHandler>? OnUserLockedOut; - /// public IEnumerable Users { @@ -234,7 +228,7 @@ namespace Jellyfin.Server.Implementations.Users dbContext.Users.Add(newUser); await dbContext.SaveChangesAsync().ConfigureAwait(false); - OnUserCreated?.Invoke(this, new GenericEventArgs(newUser)); + await _eventManager.PublishAsync(new UserCreatedEventArgs(newUser)).ConfigureAwait(false); return newUser; } @@ -293,7 +287,8 @@ namespace Jellyfin.Server.Implementations.Users dbContext.RemoveRange(user.AccessSchedules); dbContext.Users.Remove(user); dbContext.SaveChanges(); - OnUserDeleted?.Invoke(this, new GenericEventArgs(user)); + + _eventManager.Publish(new UserDeletedEventArgs(user)); } /// @@ -319,7 +314,7 @@ namespace Jellyfin.Server.Implementations.Users await GetAuthenticationProvider(user).ChangePassword(user, newPassword).ConfigureAwait(false); await UpdateUserAsync(user).ConfigureAwait(false); - OnUserPasswordChanged?.Invoke(this, new GenericEventArgs(user)); + await _eventManager.PublishAsync(new UserPasswordChangedEventArgs(user)).ConfigureAwait(false); } /// @@ -338,7 +333,7 @@ namespace Jellyfin.Server.Implementations.Users user.EasyPassword = newPasswordSha1; UpdateUser(user); - OnUserPasswordChanged?.Invoke(this, new GenericEventArgs(user)); + _eventManager.Publish(new UserPasswordChangedEventArgs(user)); } /// @@ -901,7 +896,7 @@ namespace Jellyfin.Server.Implementations.Users if (maxInvalidLogins.HasValue && user.InvalidLoginAttemptCount >= maxInvalidLogins) { user.SetPermission(PermissionKind.IsDisabled, true); - OnUserLockedOut?.Invoke(this, new GenericEventArgs(user)); + await _eventManager.PublishAsync(new UserLockedOutEventArgs(user)).ConfigureAwait(false); _logger.LogWarning( "Disabling user {Username} due to {Attempts} unsuccessful login attempts.", user.Username, diff --git a/MediaBrowser.Controller/Events/IEventManager.cs b/MediaBrowser.Controller/Events/IEventManager.cs index 794a8709e5..a1f40b3a6d 100644 --- a/MediaBrowser.Controller/Events/IEventManager.cs +++ b/MediaBrowser.Controller/Events/IEventManager.cs @@ -11,10 +11,18 @@ namespace MediaBrowser.Controller.Events /// /// Publishes an event. /// + /// the event arguments. + /// The type of event. + void Publish(T eventArgs) + where T : EventArgs; + + /// + /// Publishes an event asynchronously. + /// /// The event arguments. /// The type of event. /// A task representing the publishing of the event. - Task Publish(T eventArgs) + Task PublishAsync(T eventArgs) where T : EventArgs; } } diff --git a/MediaBrowser.Controller/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs index c8d8375b38..96a41920ab 100644 --- a/MediaBrowser.Controller/Library/IUserManager.cs +++ b/MediaBrowser.Controller/Library/IUserManager.cs @@ -19,26 +19,6 @@ namespace MediaBrowser.Controller.Library /// event EventHandler> OnUserUpdated; - /// - /// Occurs when a user is created. - /// - event EventHandler> OnUserCreated; - - /// - /// Occurs when a user is deleted. - /// - event EventHandler> OnUserDeleted; - - /// - /// Occurs when a user's password is changed. - /// - event EventHandler> OnUserPasswordChanged; - - /// - /// Occurs when a user is locked out. - /// - event EventHandler> OnUserLockedOut; - /// /// Gets the users. /// -- cgit v1.2.3 From 6f7d289feb6940afe1a266e8cec89c67b3b196ab Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 15 Aug 2020 15:55:58 -0400 Subject: Create EventManager --- .../Events/EventManager.cs | 49 ++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 Jellyfin.Server.Implementations/Events/EventManager.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Events/EventManager.cs b/Jellyfin.Server.Implementations/Events/EventManager.cs new file mode 100644 index 0000000000..d79b731063 --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/EventManager.cs @@ -0,0 +1,49 @@ +using System; +using System.Threading.Tasks; +using MediaBrowser.Controller; +using MediaBrowser.Controller.Events; +using Microsoft.Extensions.DependencyInjection; + +namespace Jellyfin.Server.Implementations.Events +{ + /// + /// Handles the firing of events. + /// + public class EventManager : IEventManager + { + private readonly IServerApplicationHost _appHost; + + /// + /// Initializes a new instance of the class. + /// + /// The application host. + public EventManager(IServerApplicationHost appHost) + { + _appHost = appHost; + } + + /// + public void Publish(T eventArgs) + where T : EventArgs + { + Task.WaitAll(PublishInternal(eventArgs)); + } + + /// + public async Task PublishAsync(T eventArgs) + where T : EventArgs + { + await PublishInternal(eventArgs).ConfigureAwait(false); + } + + private async Task PublishInternal(T eventArgs) + where T : EventArgs + { + using var scope = _appHost.ServiceProvider.CreateScope(); + foreach (var service in scope.ServiceProvider.GetServices>()) + { + await service.OnEvent(eventArgs).ConfigureAwait(false); + } + } + } +} -- cgit v1.2.3 From 8b90e0205c5bbb1c2cddd1802ce74b153b24ba77 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 15 Aug 2020 15:56:47 -0400 Subject: Add EventingServiceCollectionExtensions --- .../Events/EventingServiceCollectionExtensions.cs | 56 ++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs b/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs new file mode 100644 index 0000000000..1a43697b8a --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs @@ -0,0 +1,56 @@ +using Jellyfin.Data.Events; +using Jellyfin.Data.Events.Users; +using Jellyfin.Server.Implementations.Events.Consumers; +using Jellyfin.Server.Implementations.Events.Consumers.Library; +using Jellyfin.Server.Implementations.Events.Consumers.Security; +using Jellyfin.Server.Implementations.Events.Consumers.Session; +using Jellyfin.Server.Implementations.Events.Consumers.Updates; +using Jellyfin.Server.Implementations.Events.Consumers.Users; +using MediaBrowser.Common.Updates; +using MediaBrowser.Controller.Authentication; +using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Events.Session; +using MediaBrowser.Controller.Events.Updates; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Session; +using MediaBrowser.Controller.Subtitles; +using MediaBrowser.Model.Tasks; +using Microsoft.Extensions.DependencyInjection; + +namespace Jellyfin.Server.Implementations.Events +{ + /// + /// A class containing extensions to for eventing. + /// + public static class EventingServiceCollectionExtensions + { + /// + /// Adds the event services to the service collection. + /// + /// The service collection. + public static void AddEventServices(this IServiceCollection collection) + { + collection.AddScoped, SubtitleDownloadFailureLogger>(); + + collection.AddScoped>, AuthenticationSucceededLogger>(); + collection.AddScoped>, AuthenticationFailedLogger>(); + + collection.AddScoped, PlaybackStartLogger>(); + collection.AddScoped, PlaybackStopLogger>(); + collection.AddScoped, SessionStartedLogger>(); + collection.AddScoped, SessionEndedLogger>(); + + collection.AddScoped, PluginInstalledLogger>(); + collection.AddScoped, PluginUninstalledLogger>(); + collection.AddScoped, PluginUpdatedLogger>(); + collection.AddScoped, PackageInstallationFailedLogger>(); + + collection.AddScoped, UserCreatedLogger>(); + collection.AddScoped, UserDeletedLogger>(); + collection.AddScoped, UserLockedOutLogger>(); + collection.AddScoped, UserPasswordChangedLogger>(); + + collection.AddScoped, TaskCompletedLogger>(); + } + } +} -- cgit v1.2.3 From a0453a0fe65d19d0484cc83ce2f31b08dadcfd09 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 15 Aug 2020 18:16:20 -0400 Subject: Migrate ServerEventNotifier.OnUserUpdated to IEventConsumer --- .../EntryPoints/ServerEventNotifier.cs | 44 ------ Jellyfin.Data/Events/Users/UserUpdatedEventArgs.cs | 18 +++ .../Events/Consumers/System/TaskCompletedLogger.cs | 158 +++++++++++++++++++++ .../Events/Consumers/TaskCompletedLogger.cs | 158 --------------------- .../Events/Consumers/Users/UserUpdatedNotifier.cs | 41 ++++++ .../Events/EventingServiceCollectionExtensions.cs | 4 +- 6 files changed, 220 insertions(+), 203 deletions(-) create mode 100644 Jellyfin.Data/Events/Users/UserUpdatedEventArgs.cs create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/System/TaskCompletedLogger.cs delete mode 100644 Jellyfin.Server.Implementations/Events/Consumers/TaskCompletedLogger.cs create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Users/UserUpdatedNotifier.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs index 1ec1f08683..0e50866851 100644 --- a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs @@ -1,16 +1,11 @@ using System; -using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using Jellyfin.Data.Entities; -using Jellyfin.Data.Events; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; using MediaBrowser.Controller; -using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Tasks; using MediaBrowser.Model.Updates; namespace Emby.Server.Implementations.EntryPoints @@ -20,11 +15,6 @@ namespace Emby.Server.Implementations.EntryPoints /// public class ServerEventNotifier : IServerEntryPoint { - /// - /// The user manager. - /// - private readonly IUserManager _userManager; - /// /// The installation manager. /// @@ -46,18 +36,15 @@ namespace Emby.Server.Implementations.EntryPoints /// Initializes a new instance of the class. /// /// The application host. - /// The user manager. /// The installation manager. /// The task manager. /// The session manager. public ServerEventNotifier( IServerApplicationHost appHost, - IUserManager userManager, IInstallationManager installationManager, ITaskManager taskManager, ISessionManager sessionManager) { - _userManager = userManager; _installationManager = installationManager; _appHost = appHost; _taskManager = taskManager; @@ -67,8 +54,6 @@ namespace Emby.Server.Implementations.EntryPoints /// public Task RunAsync() { - _userManager.OnUserUpdated += OnUserUpdated; - _appHost.HasPendingRestartChanged += OnHasPendingRestartChanged; _installationManager.PluginUninstalled += OnPluginUninstalled; @@ -127,18 +112,6 @@ namespace Emby.Server.Implementations.EntryPoints await _sessionManager.SendRestartRequiredNotification(CancellationToken.None).ConfigureAwait(false); } - /// - /// Users the manager_ user updated. - /// - /// The sender. - /// The e. - private async void OnUserUpdated(object sender, GenericEventArgs e) - { - var dto = _userManager.GetUserDto(e.Argument); - - await SendMessageToUserSession(e.Argument, "UserUpdated", dto).ConfigureAwait(false); - } - private async Task SendMessageToAdminSessions(string name, T data) { try @@ -150,21 +123,6 @@ namespace Emby.Server.Implementations.EntryPoints } } - private async Task SendMessageToUserSession(User user, string name, T data) - { - try - { - await _sessionManager.SendMessageToUserSessions( - new List { user.Id }, - name, - data, - CancellationToken.None).ConfigureAwait(false); - } - catch (Exception) - { - } - } - /// public void Dispose() { @@ -180,8 +138,6 @@ namespace Emby.Server.Implementations.EntryPoints { if (dispose) { - _userManager.OnUserUpdated -= OnUserUpdated; - _installationManager.PluginUninstalled -= OnPluginUninstalled; _installationManager.PackageInstalling -= OnPackageInstalling; _installationManager.PackageInstallationCancelled -= OnPackageInstallationCancelled; diff --git a/Jellyfin.Data/Events/Users/UserUpdatedEventArgs.cs b/Jellyfin.Data/Events/Users/UserUpdatedEventArgs.cs new file mode 100644 index 0000000000..2b4e49cdf6 --- /dev/null +++ b/Jellyfin.Data/Events/Users/UserUpdatedEventArgs.cs @@ -0,0 +1,18 @@ +using Jellyfin.Data.Entities; + +namespace Jellyfin.Data.Events.Users +{ + /// + /// An event that occurs when a user is updated. + /// + public class UserUpdatedEventArgs : GenericEventArgs + { + /// + /// Initializes a new instance of the class. + /// + /// The user. + public UserUpdatedEventArgs(User arg) : base(arg) + { + } + } +} diff --git a/Jellyfin.Server.Implementations/Events/Consumers/System/TaskCompletedLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/System/TaskCompletedLogger.cs new file mode 100644 index 0000000000..05201a3469 --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/System/TaskCompletedLogger.cs @@ -0,0 +1,158 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; +using System.Threading.Tasks; +using Jellyfin.Data.Entities; +using MediaBrowser.Controller.Events; +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.Notifications; +using MediaBrowser.Model.Tasks; +using Microsoft.Extensions.Logging; + +namespace Jellyfin.Server.Implementations.Events.Consumers.System +{ + /// + /// Creates an activity log entry whenever a task is completed. + /// + public class TaskCompletedLogger : IEventConsumer + { + private readonly ILocalizationManager _localizationManager; + private readonly IActivityManager _activityManager; + + /// + /// Initializes a new instance of the class. + /// + /// The localization manager. + /// The activity manager. + public TaskCompletedLogger(ILocalizationManager localizationManager, IActivityManager activityManager) + { + _localizationManager = localizationManager; + _activityManager = activityManager; + } + + /// + public async Task OnEvent(TaskCompletionEventArgs e) + { + var result = e.Result; + var task = e.Task; + + if (task.ScheduledTask is IConfigurableScheduledTask activityTask + && !activityTask.IsLogged) + { + return; + } + + var time = result.EndTimeUtc - result.StartTimeUtc; + var runningTime = string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("LabelRunningTimeValue"), + ToUserFriendlyString(time)); + + if (result.Status == TaskCompletionStatus.Failed) + { + var vals = new List(); + + if (!string.IsNullOrEmpty(e.Result.ErrorMessage)) + { + vals.Add(e.Result.ErrorMessage); + } + + if (!string.IsNullOrEmpty(e.Result.LongErrorMessage)) + { + vals.Add(e.Result.LongErrorMessage); + } + + await _activityManager.CreateAsync(new ActivityLog( + string.Format(CultureInfo.InvariantCulture, _localizationManager.GetLocalizedString("ScheduledTaskFailedWithName"), task.Name), + NotificationType.TaskFailed.ToString(), + Guid.Empty) + { + LogSeverity = LogLevel.Error, + Overview = string.Join(Environment.NewLine, vals), + ShortOverview = runningTime + }).ConfigureAwait(false); + } + } + + private static string ToUserFriendlyString(TimeSpan span) + { + const int DaysInYear = 365; + const int DaysInMonth = 30; + + // Get each non-zero value from TimeSpan component + var values = new List(); + + // Number of years + int days = span.Days; + if (days >= DaysInYear) + { + int years = days / DaysInYear; + values.Add(CreateValueString(years, "year")); + days %= DaysInYear; + } + + // Number of months + if (days >= DaysInMonth) + { + int months = days / DaysInMonth; + values.Add(CreateValueString(months, "month")); + days = days % DaysInMonth; + } + + // Number of days + if (days >= 1) + { + values.Add(CreateValueString(days, "day")); + } + + // Number of hours + if (span.Hours >= 1) + { + values.Add(CreateValueString(span.Hours, "hour")); + } + + // Number of minutes + if (span.Minutes >= 1) + { + values.Add(CreateValueString(span.Minutes, "minute")); + } + + // Number of seconds (include when 0 if no other components included) + if (span.Seconds >= 1 || values.Count == 0) + { + values.Add(CreateValueString(span.Seconds, "second")); + } + + // Combine values into string + var builder = new StringBuilder(); + for (int i = 0; i < values.Count; i++) + { + if (builder.Length > 0) + { + builder.Append(i == values.Count - 1 ? " and " : ", "); + } + + builder.Append(values[i]); + } + + // Return result + return builder.ToString(); + } + + /// + /// Constructs a string description of a time-span value. + /// + /// The value of this item. + /// The name of this item (singular form). + private static string CreateValueString(int value, string description) + { + return string.Format( + CultureInfo.InvariantCulture, + "{0:#,##0} {1}", + value, + value == 1 ? description : string.Format(CultureInfo.InvariantCulture, "{0}s", description)); + } + } +} diff --git a/Jellyfin.Server.Implementations/Events/Consumers/TaskCompletedLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/TaskCompletedLogger.cs deleted file mode 100644 index 7f737ee7e6..0000000000 --- a/Jellyfin.Server.Implementations/Events/Consumers/TaskCompletedLogger.cs +++ /dev/null @@ -1,158 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Text; -using System.Threading.Tasks; -using Jellyfin.Data.Entities; -using MediaBrowser.Controller.Events; -using MediaBrowser.Model.Activity; -using MediaBrowser.Model.Globalization; -using MediaBrowser.Model.Notifications; -using MediaBrowser.Model.Tasks; -using Microsoft.Extensions.Logging; - -namespace Jellyfin.Server.Implementations.Events.Consumers -{ - /// - /// Creates an activity log entry whenever a task is completed. - /// - public class TaskCompletedLogger : IEventConsumer - { - private readonly ILocalizationManager _localizationManager; - private readonly IActivityManager _activityManager; - - /// - /// Initializes a new instance of the class. - /// - /// The localization manager. - /// The activity manager. - public TaskCompletedLogger(ILocalizationManager localizationManager, IActivityManager activityManager) - { - _localizationManager = localizationManager; - _activityManager = activityManager; - } - - /// - public async Task OnEvent(TaskCompletionEventArgs e) - { - var result = e.Result; - var task = e.Task; - - if (task.ScheduledTask is IConfigurableScheduledTask activityTask - && !activityTask.IsLogged) - { - return; - } - - var time = result.EndTimeUtc - result.StartTimeUtc; - var runningTime = string.Format( - CultureInfo.InvariantCulture, - _localizationManager.GetLocalizedString("LabelRunningTimeValue"), - ToUserFriendlyString(time)); - - if (result.Status == TaskCompletionStatus.Failed) - { - var vals = new List(); - - if (!string.IsNullOrEmpty(e.Result.ErrorMessage)) - { - vals.Add(e.Result.ErrorMessage); - } - - if (!string.IsNullOrEmpty(e.Result.LongErrorMessage)) - { - vals.Add(e.Result.LongErrorMessage); - } - - await _activityManager.CreateAsync(new ActivityLog( - string.Format(CultureInfo.InvariantCulture, _localizationManager.GetLocalizedString("ScheduledTaskFailedWithName"), task.Name), - NotificationType.TaskFailed.ToString(), - Guid.Empty) - { - LogSeverity = LogLevel.Error, - Overview = string.Join(Environment.NewLine, vals), - ShortOverview = runningTime - }).ConfigureAwait(false); - } - } - - private static string ToUserFriendlyString(TimeSpan span) - { - const int DaysInYear = 365; - const int DaysInMonth = 30; - - // Get each non-zero value from TimeSpan component - var values = new List(); - - // Number of years - int days = span.Days; - if (days >= DaysInYear) - { - int years = days / DaysInYear; - values.Add(CreateValueString(years, "year")); - days %= DaysInYear; - } - - // Number of months - if (days >= DaysInMonth) - { - int months = days / DaysInMonth; - values.Add(CreateValueString(months, "month")); - days = days % DaysInMonth; - } - - // Number of days - if (days >= 1) - { - values.Add(CreateValueString(days, "day")); - } - - // Number of hours - if (span.Hours >= 1) - { - values.Add(CreateValueString(span.Hours, "hour")); - } - - // Number of minutes - if (span.Minutes >= 1) - { - values.Add(CreateValueString(span.Minutes, "minute")); - } - - // Number of seconds (include when 0 if no other components included) - if (span.Seconds >= 1 || values.Count == 0) - { - values.Add(CreateValueString(span.Seconds, "second")); - } - - // Combine values into string - var builder = new StringBuilder(); - for (int i = 0; i < values.Count; i++) - { - if (builder.Length > 0) - { - builder.Append(i == values.Count - 1 ? " and " : ", "); - } - - builder.Append(values[i]); - } - - // Return result - return builder.ToString(); - } - - /// - /// Constructs a string description of a time-span value. - /// - /// The value of this item. - /// The name of this item (singular form). - private static string CreateValueString(int value, string description) - { - return string.Format( - CultureInfo.InvariantCulture, - "{0:#,##0} {1}", - value, - value == 1 ? description : string.Format(CultureInfo.InvariantCulture, "{0}s", description)); - } - } -} diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Users/UserUpdatedNotifier.cs b/Jellyfin.Server.Implementations/Events/Consumers/Users/UserUpdatedNotifier.cs new file mode 100644 index 0000000000..6081dd044f --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Users/UserUpdatedNotifier.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Jellyfin.Data.Events.Users; +using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Session; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Users +{ + /// + /// Notifies a user when their account has been updated. + /// + public class UserUpdatedNotifier : IEventConsumer + { + private readonly IUserManager _userManager; + private readonly ISessionManager _sessionManager; + + /// + /// Initializes a new instance of the class. + /// + /// The user manager. + /// The session manager. + public UserUpdatedNotifier(IUserManager userManager, ISessionManager sessionManager) + { + _userManager = userManager; + _sessionManager = sessionManager; + } + + /// + public async Task OnEvent(UserUpdatedEventArgs e) + { + await _sessionManager.SendMessageToUserSessions( + new List { e.Argument.Id }, + "UserUpdated", + _userManager.GetUserDto(e.Argument), + CancellationToken.None).ConfigureAwait(false); + } + } +} diff --git a/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs b/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs index 1a43697b8a..84181f4fee 100644 --- a/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs +++ b/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs @@ -1,9 +1,9 @@ using Jellyfin.Data.Events; using Jellyfin.Data.Events.Users; -using Jellyfin.Server.Implementations.Events.Consumers; using Jellyfin.Server.Implementations.Events.Consumers.Library; using Jellyfin.Server.Implementations.Events.Consumers.Security; using Jellyfin.Server.Implementations.Events.Consumers.Session; +using Jellyfin.Server.Implementations.Events.Consumers.System; using Jellyfin.Server.Implementations.Events.Consumers.Updates; using Jellyfin.Server.Implementations.Events.Consumers.Users; using MediaBrowser.Common.Updates; @@ -47,6 +47,8 @@ namespace Jellyfin.Server.Implementations.Events collection.AddScoped, UserCreatedLogger>(); collection.AddScoped, UserDeletedLogger>(); + collection.AddScoped, UserDeletedNotifier>(); + collection.AddScoped, UserUpdatedNotifier>(); collection.AddScoped, UserLockedOutLogger>(); collection.AddScoped, UserPasswordChangedLogger>(); -- cgit v1.2.3 From 5282a5c8c2224ec36121cdf99ef2a14f7d703973 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 15 Aug 2020 18:16:41 -0400 Subject: Migrate ServerEventNotifier.OnTaskCompleted to IEventConsumer --- .../EntryPoints/ServerEventNotifier.cs | 17 ------------ .../Consumers/System/TaskCompletedNotifier.cs | 31 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 17 deletions(-) create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/System/TaskCompletedNotifier.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs index 0e50866851..833c061066 100644 --- a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs @@ -25,11 +25,6 @@ namespace Emby.Server.Implementations.EntryPoints /// private readonly IServerApplicationHost _appHost; - /// - /// The task manager. - /// - private readonly ITaskManager _taskManager; - private readonly ISessionManager _sessionManager; /// @@ -37,17 +32,14 @@ namespace Emby.Server.Implementations.EntryPoints /// /// The application host. /// The installation manager. - /// The task manager. /// The session manager. public ServerEventNotifier( IServerApplicationHost appHost, IInstallationManager installationManager, - ITaskManager taskManager, ISessionManager sessionManager) { _installationManager = installationManager; _appHost = appHost; - _taskManager = taskManager; _sessionManager = sessionManager; } @@ -62,8 +54,6 @@ namespace Emby.Server.Implementations.EntryPoints _installationManager.PackageInstallationCompleted += OnPackageInstallationCompleted; _installationManager.PackageInstallationFailed += OnPackageInstallationFailed; - _taskManager.TaskCompleted += OnTaskCompleted; - return Task.CompletedTask; } @@ -87,11 +77,6 @@ namespace Emby.Server.Implementations.EntryPoints await SendMessageToAdminSessions("PackageInstallationFailed", e.InstallationInfo).ConfigureAwait(false); } - private async void OnTaskCompleted(object sender, TaskCompletionEventArgs e) - { - await SendMessageToAdminSessions("ScheduledTaskEnded", e.Result).ConfigureAwait(false); - } - /// /// Installations the manager_ plugin uninstalled. /// @@ -145,8 +130,6 @@ namespace Emby.Server.Implementations.EntryPoints _installationManager.PackageInstallationFailed -= OnPackageInstallationFailed; _appHost.HasPendingRestartChanged -= OnHasPendingRestartChanged; - - _taskManager.TaskCompleted -= OnTaskCompleted; } } } diff --git a/Jellyfin.Server.Implementations/Events/Consumers/System/TaskCompletedNotifier.cs b/Jellyfin.Server.Implementations/Events/Consumers/System/TaskCompletedNotifier.cs new file mode 100644 index 0000000000..80ed56cd8f --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/System/TaskCompletedNotifier.cs @@ -0,0 +1,31 @@ +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Tasks; + +namespace Jellyfin.Server.Implementations.Events.Consumers.System +{ + /// + /// Notifies admin users when a task is completed. + /// + public class TaskCompletedNotifier : IEventConsumer + { + private readonly ISessionManager _sessionManager; + + /// + /// Initializes a new instance of the class. + /// + /// The session manager. + public TaskCompletedNotifier(ISessionManager sessionManager) + { + _sessionManager = sessionManager; + } + + /// + public async Task OnEvent(TaskCompletionEventArgs eventArgs) + { + await _sessionManager.SendMessageToAdminSessions("ScheduledTaskEnded", eventArgs.Result, CancellationToken.None).ConfigureAwait(false); + } + } +} -- cgit v1.2.3 From dc88e93504a98a377881f7425ffba5d2221fada0 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 15 Aug 2020 18:33:30 -0400 Subject: Migrate ServerEventNotifier.OnHasPendingRestartChanged to IEventConsumer --- .../EntryPoints/ServerEventNotifier.cs | 23 ---------------- .../Events/System/PendingRestartEventArgs.cs | 11 ++++++++ .../Consumers/System/PendingRestartNotifier.cs | 31 ++++++++++++++++++++++ 3 files changed, 42 insertions(+), 23 deletions(-) create mode 100644 Jellyfin.Data/Events/System/PendingRestartEventArgs.cs create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/System/PendingRestartNotifier.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs index 833c061066..3d58b91e1d 100644 --- a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs @@ -3,7 +3,6 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; -using MediaBrowser.Controller; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Updates; @@ -20,34 +19,24 @@ namespace Emby.Server.Implementations.EntryPoints /// private readonly IInstallationManager _installationManager; - /// - /// The kernel. - /// - private readonly IServerApplicationHost _appHost; - private readonly ISessionManager _sessionManager; /// /// Initializes a new instance of the class. /// - /// The application host. /// The installation manager. /// The session manager. public ServerEventNotifier( - IServerApplicationHost appHost, IInstallationManager installationManager, ISessionManager sessionManager) { _installationManager = installationManager; - _appHost = appHost; _sessionManager = sessionManager; } /// public Task RunAsync() { - _appHost.HasPendingRestartChanged += OnHasPendingRestartChanged; - _installationManager.PluginUninstalled += OnPluginUninstalled; _installationManager.PackageInstalling += OnPackageInstalling; _installationManager.PackageInstallationCancelled += OnPackageInstallationCancelled; @@ -87,16 +76,6 @@ namespace Emby.Server.Implementations.EntryPoints await SendMessageToAdminSessions("PluginUninstalled", e).ConfigureAwait(false); } - /// - /// Handles the HasPendingRestartChanged event of the kernel control. - /// - /// The source of the event. - /// The instance containing the event data. - private async void OnHasPendingRestartChanged(object sender, EventArgs e) - { - await _sessionManager.SendRestartRequiredNotification(CancellationToken.None).ConfigureAwait(false); - } - private async Task SendMessageToAdminSessions(string name, T data) { try @@ -128,8 +107,6 @@ namespace Emby.Server.Implementations.EntryPoints _installationManager.PackageInstallationCancelled -= OnPackageInstallationCancelled; _installationManager.PackageInstallationCompleted -= OnPackageInstallationCompleted; _installationManager.PackageInstallationFailed -= OnPackageInstallationFailed; - - _appHost.HasPendingRestartChanged -= OnHasPendingRestartChanged; } } } diff --git a/Jellyfin.Data/Events/System/PendingRestartEventArgs.cs b/Jellyfin.Data/Events/System/PendingRestartEventArgs.cs new file mode 100644 index 0000000000..17a4549699 --- /dev/null +++ b/Jellyfin.Data/Events/System/PendingRestartEventArgs.cs @@ -0,0 +1,11 @@ +using System; + +namespace Jellyfin.Data.Events.System +{ + /// + /// An event that fires when there is a pending restart. + /// + public class PendingRestartEventArgs : EventArgs + { + } +} diff --git a/Jellyfin.Server.Implementations/Events/Consumers/System/PendingRestartNotifier.cs b/Jellyfin.Server.Implementations/Events/Consumers/System/PendingRestartNotifier.cs new file mode 100644 index 0000000000..2fa38dd71a --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/System/PendingRestartNotifier.cs @@ -0,0 +1,31 @@ +using System.Threading; +using System.Threading.Tasks; +using Jellyfin.Data.Events.System; +using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Session; + +namespace Jellyfin.Server.Implementations.Events.Consumers.System +{ + /// + /// Notifies users when there is a pending restart. + /// + public class PendingRestartNotifier : IEventConsumer + { + private readonly ISessionManager _sessionManager; + + /// + /// Initializes a new instance of the class. + /// + /// The session manager. + public PendingRestartNotifier(ISessionManager sessionManager) + { + _sessionManager = sessionManager; + } + + /// + public async Task OnEvent(PendingRestartEventArgs eventArgs) + { + await _sessionManager.SendRestartRequiredNotification(CancellationToken.None).ConfigureAwait(false); + } + } +} -- cgit v1.2.3 From b2f734efd127c04815d0a4799dd20449b96c501b Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 15 Aug 2020 18:36:37 -0400 Subject: Gracefully handle exceptions in IEventConsumers --- Jellyfin.Server.Implementations/Events/EventManager.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Events/EventManager.cs b/Jellyfin.Server.Implementations/Events/EventManager.cs index d79b731063..7070024422 100644 --- a/Jellyfin.Server.Implementations/Events/EventManager.cs +++ b/Jellyfin.Server.Implementations/Events/EventManager.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using MediaBrowser.Controller; using MediaBrowser.Controller.Events; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; namespace Jellyfin.Server.Implementations.Events { @@ -11,14 +12,17 @@ namespace Jellyfin.Server.Implementations.Events /// public class EventManager : IEventManager { + private readonly ILogger _logger; private readonly IServerApplicationHost _appHost; /// /// Initializes a new instance of the class. /// + /// The logger. /// The application host. - public EventManager(IServerApplicationHost appHost) + public EventManager(ILogger logger, IServerApplicationHost appHost) { + _logger = logger; _appHost = appHost; } @@ -42,7 +46,14 @@ namespace Jellyfin.Server.Implementations.Events using var scope = _appHost.ServiceProvider.CreateScope(); foreach (var service in scope.ServiceProvider.GetServices>()) { - await service.OnEvent(eventArgs).ConfigureAwait(false); + try + { + await service.OnEvent(eventArgs).ConfigureAwait(false); + } + catch (Exception e) + { + _logger.LogError(e, "Uncaught exception in EventConsumer {type}: ", service.GetType()); + } } } } -- cgit v1.2.3 From b7ceb40d6efe083653734e6417b2f5e48b522872 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 15 Aug 2020 18:57:46 -0400 Subject: Migrate ServerEventNotifier.OnPackageInstalling to IEventConsumer --- .../EntryPoints/ServerEventNotifier.cs | 7 ----- .../Consumers/Updates/PluginInstallingNotifier.cs | 31 ++++++++++++++++++++++ .../Events/Updates/PluginInstallingEventArgs.cs | 19 +++++++++++++ 3 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallingNotifier.cs create mode 100644 MediaBrowser.Controller/Events/Updates/PluginInstallingEventArgs.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs index 3d58b91e1d..068872420b 100644 --- a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs @@ -38,7 +38,6 @@ namespace Emby.Server.Implementations.EntryPoints public Task RunAsync() { _installationManager.PluginUninstalled += OnPluginUninstalled; - _installationManager.PackageInstalling += OnPackageInstalling; _installationManager.PackageInstallationCancelled += OnPackageInstallationCancelled; _installationManager.PackageInstallationCompleted += OnPackageInstallationCompleted; _installationManager.PackageInstallationFailed += OnPackageInstallationFailed; @@ -46,11 +45,6 @@ namespace Emby.Server.Implementations.EntryPoints return Task.CompletedTask; } - private async void OnPackageInstalling(object sender, InstallationInfo e) - { - await SendMessageToAdminSessions("PackageInstalling", e).ConfigureAwait(false); - } - private async void OnPackageInstallationCancelled(object sender, InstallationInfo e) { await SendMessageToAdminSessions("PackageInstallationCancelled", e).ConfigureAwait(false); @@ -103,7 +97,6 @@ namespace Emby.Server.Implementations.EntryPoints if (dispose) { _installationManager.PluginUninstalled -= OnPluginUninstalled; - _installationManager.PackageInstalling -= OnPackageInstalling; _installationManager.PackageInstallationCancelled -= OnPackageInstallationCancelled; _installationManager.PackageInstallationCompleted -= OnPackageInstallationCompleted; _installationManager.PackageInstallationFailed -= OnPackageInstallationFailed; diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallingNotifier.cs b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallingNotifier.cs new file mode 100644 index 0000000000..f691d11a7d --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallingNotifier.cs @@ -0,0 +1,31 @@ +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Events.Updates; +using MediaBrowser.Controller.Session; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Updates +{ + /// + /// Notifies admin users when a plugin is being installed. + /// + public class PluginInstallingNotifier : IEventConsumer + { + private readonly ISessionManager _sessionManager; + + /// + /// Initializes a new instance of the class. + /// + /// The session manager. + public PluginInstallingNotifier(ISessionManager sessionManager) + { + _sessionManager = sessionManager; + } + + /// + public async Task OnEvent(PluginInstallingEventArgs eventArgs) + { + await _sessionManager.SendMessageToAdminSessions("PackageInstalling", eventArgs.Argument, CancellationToken.None).ConfigureAwait(false); + } + } +} diff --git a/MediaBrowser.Controller/Events/Updates/PluginInstallingEventArgs.cs b/MediaBrowser.Controller/Events/Updates/PluginInstallingEventArgs.cs new file mode 100644 index 0000000000..045a600272 --- /dev/null +++ b/MediaBrowser.Controller/Events/Updates/PluginInstallingEventArgs.cs @@ -0,0 +1,19 @@ +using Jellyfin.Data.Events; +using MediaBrowser.Model.Updates; + +namespace MediaBrowser.Controller.Events.Updates +{ + /// + /// An event that occurs when a plugin is installing. + /// + public class PluginInstallingEventArgs : GenericEventArgs + { + /// + /// Initializes a new instance of the class. + /// + /// The installation info. + public PluginInstallingEventArgs(InstallationInfo arg) : base(arg) + { + } + } +} -- cgit v1.2.3 From 4478945e20e0861c720a1035778f3f13be90226d Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 15 Aug 2020 23:12:01 -0400 Subject: Migrate ServerEventNotifier.OnPluginUninstalled to IEventConsumer --- .../EntryPoints/ServerEventNotifier.cs | 13 --------- .../Consumers/Updates/PluginUninstalledNotifier.cs | 31 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 13 deletions(-) create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUninstalledNotifier.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs index 068872420b..247bb87c75 100644 --- a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs @@ -1,7 +1,6 @@ using System; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; @@ -37,7 +36,6 @@ namespace Emby.Server.Implementations.EntryPoints /// public Task RunAsync() { - _installationManager.PluginUninstalled += OnPluginUninstalled; _installationManager.PackageInstallationCancelled += OnPackageInstallationCancelled; _installationManager.PackageInstallationCompleted += OnPackageInstallationCompleted; _installationManager.PackageInstallationFailed += OnPackageInstallationFailed; @@ -60,16 +58,6 @@ namespace Emby.Server.Implementations.EntryPoints await SendMessageToAdminSessions("PackageInstallationFailed", e.InstallationInfo).ConfigureAwait(false); } - /// - /// Installations the manager_ plugin uninstalled. - /// - /// The sender. - /// The e. - private async void OnPluginUninstalled(object sender, IPlugin e) - { - await SendMessageToAdminSessions("PluginUninstalled", e).ConfigureAwait(false); - } - private async Task SendMessageToAdminSessions(string name, T data) { try @@ -96,7 +84,6 @@ namespace Emby.Server.Implementations.EntryPoints { if (dispose) { - _installationManager.PluginUninstalled -= OnPluginUninstalled; _installationManager.PackageInstallationCancelled -= OnPackageInstallationCancelled; _installationManager.PackageInstallationCompleted -= OnPackageInstallationCompleted; _installationManager.PackageInstallationFailed -= OnPackageInstallationFailed; diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUninstalledNotifier.cs b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUninstalledNotifier.cs new file mode 100644 index 0000000000..709692f6bb --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUninstalledNotifier.cs @@ -0,0 +1,31 @@ +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Events.Updates; +using MediaBrowser.Controller.Session; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Updates +{ + /// + /// Notifies admin users when a plugin is uninstalled. + /// + public class PluginUninstalledNotifier : IEventConsumer + { + private readonly ISessionManager _sessionManager; + + /// + /// Initializes a new instance of the class. + /// + /// The session manager. + public PluginUninstalledNotifier(ISessionManager sessionManager) + { + _sessionManager = sessionManager; + } + + /// + public async Task OnEvent(PluginUninstalledEventArgs eventArgs) + { + await _sessionManager.SendMessageToAdminSessions("PluginUninstalled", eventArgs.Argument, CancellationToken.None).ConfigureAwait(false); + } + } +} -- cgit v1.2.3 From 25437af594bbac517ab3a9bfef26e2b4af7ee899 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 15 Aug 2020 23:12:34 -0400 Subject: Migrate ServerEventNotifier.OnPackageInstallationFailed to IEventConsumer --- .../EntryPoints/ServerEventNotifier.cs | 7 ----- .../Updates/PluginInstallationFailedNotifier.cs | 31 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallationFailedNotifier.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs index 247bb87c75..549e1d5690 100644 --- a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs @@ -38,7 +38,6 @@ namespace Emby.Server.Implementations.EntryPoints { _installationManager.PackageInstallationCancelled += OnPackageInstallationCancelled; _installationManager.PackageInstallationCompleted += OnPackageInstallationCompleted; - _installationManager.PackageInstallationFailed += OnPackageInstallationFailed; return Task.CompletedTask; } @@ -53,11 +52,6 @@ namespace Emby.Server.Implementations.EntryPoints await SendMessageToAdminSessions("PackageInstallationCompleted", e).ConfigureAwait(false); } - private async void OnPackageInstallationFailed(object sender, InstallationFailedEventArgs e) - { - await SendMessageToAdminSessions("PackageInstallationFailed", e.InstallationInfo).ConfigureAwait(false); - } - private async Task SendMessageToAdminSessions(string name, T data) { try @@ -86,7 +80,6 @@ namespace Emby.Server.Implementations.EntryPoints { _installationManager.PackageInstallationCancelled -= OnPackageInstallationCancelled; _installationManager.PackageInstallationCompleted -= OnPackageInstallationCompleted; - _installationManager.PackageInstallationFailed -= OnPackageInstallationFailed; } } } diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallationFailedNotifier.cs b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallationFailedNotifier.cs new file mode 100644 index 0000000000..ea0c878d42 --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallationFailedNotifier.cs @@ -0,0 +1,31 @@ +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Common.Updates; +using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Session; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Updates +{ + /// + /// Notifies admin users when a plugin installation fails. + /// + public class PluginInstallationFailedNotifier : IEventConsumer + { + private readonly ISessionManager _sessionManager; + + /// + /// Initializes a new instance of the class. + /// + /// The session manager. + public PluginInstallationFailedNotifier(ISessionManager sessionManager) + { + _sessionManager = sessionManager; + } + + /// + public async Task OnEvent(InstallationFailedEventArgs eventArgs) + { + await _sessionManager.SendMessageToAdminSessions("PackageInstallationFailed", eventArgs.InstallationInfo, CancellationToken.None).ConfigureAwait(false); + } + } +} -- cgit v1.2.3 From e82dd8b70ee5fe1d09c7230a7de21f47456b8c55 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 15 Aug 2020 23:16:15 -0400 Subject: Migrate ServerEventNotifier.OnPackageInstallationCompleted to IEventConsumer --- .../EntryPoints/ServerEventNotifier.cs | 7 ----- .../Consumers/Updates/PluginInstalledNotifier.cs | 31 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstalledNotifier.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs index 549e1d5690..1fbb9f3037 100644 --- a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs @@ -37,7 +37,6 @@ namespace Emby.Server.Implementations.EntryPoints public Task RunAsync() { _installationManager.PackageInstallationCancelled += OnPackageInstallationCancelled; - _installationManager.PackageInstallationCompleted += OnPackageInstallationCompleted; return Task.CompletedTask; } @@ -47,11 +46,6 @@ namespace Emby.Server.Implementations.EntryPoints await SendMessageToAdminSessions("PackageInstallationCancelled", e).ConfigureAwait(false); } - private async void OnPackageInstallationCompleted(object sender, InstallationInfo e) - { - await SendMessageToAdminSessions("PackageInstallationCompleted", e).ConfigureAwait(false); - } - private async Task SendMessageToAdminSessions(string name, T data) { try @@ -79,7 +73,6 @@ namespace Emby.Server.Implementations.EntryPoints if (dispose) { _installationManager.PackageInstallationCancelled -= OnPackageInstallationCancelled; - _installationManager.PackageInstallationCompleted -= OnPackageInstallationCompleted; } } } diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstalledNotifier.cs b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstalledNotifier.cs new file mode 100644 index 0000000000..3dda5a04c4 --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstalledNotifier.cs @@ -0,0 +1,31 @@ +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Events.Updates; +using MediaBrowser.Controller.Session; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Updates +{ + /// + /// Notifies admin users when a plugin is installed. + /// + public class PluginInstalledNotifier : IEventConsumer + { + private readonly ISessionManager _sessionManager; + + /// + /// Initializes a new instance of the class. + /// + /// The session manager. + public PluginInstalledNotifier(ISessionManager sessionManager) + { + _sessionManager = sessionManager; + } + + /// + public async Task OnEvent(PluginInstalledEventArgs eventArgs) + { + await _sessionManager.SendMessageToAdminSessions("PackageInstallationCompleted", eventArgs.Argument, CancellationToken.None).ConfigureAwait(false); + } + } +} -- cgit v1.2.3 From a40064a146da17a49582f7ef1ad754a497725ccc Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 15 Aug 2020 23:20:41 -0400 Subject: Migrate ServerEventNotifier.OnPackageInstallationCancelled to IEventConsumer --- .../EntryPoints/ServerEventNotifier.cs | 79 ---------------------- .../Updates/PluginInstallationCancelledNotifier.cs | 31 +++++++++ .../PluginInstallationCancelledEventArgs.cs | 19 ++++++ 3 files changed, 50 insertions(+), 79 deletions(-) delete mode 100644 Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallationCancelledNotifier.cs create mode 100644 MediaBrowser.Controller/Events/Updates/PluginInstallationCancelledEventArgs.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs deleted file mode 100644 index 1fbb9f3037..0000000000 --- a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.Updates; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Updates; - -namespace Emby.Server.Implementations.EntryPoints -{ - /// - /// Class WebSocketEvents. - /// - public class ServerEventNotifier : IServerEntryPoint - { - /// - /// The installation manager. - /// - private readonly IInstallationManager _installationManager; - - private readonly ISessionManager _sessionManager; - - /// - /// Initializes a new instance of the class. - /// - /// The installation manager. - /// The session manager. - public ServerEventNotifier( - IInstallationManager installationManager, - ISessionManager sessionManager) - { - _installationManager = installationManager; - _sessionManager = sessionManager; - } - - /// - public Task RunAsync() - { - _installationManager.PackageInstallationCancelled += OnPackageInstallationCancelled; - - return Task.CompletedTask; - } - - private async void OnPackageInstallationCancelled(object sender, InstallationInfo e) - { - await SendMessageToAdminSessions("PackageInstallationCancelled", e).ConfigureAwait(false); - } - - private async Task SendMessageToAdminSessions(string name, T data) - { - try - { - await _sessionManager.SendMessageToAdminSessions(name, data, CancellationToken.None).ConfigureAwait(false); - } - catch (Exception) - { - } - } - - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// Releases unmanaged and - optionally - managed resources. - /// - /// true to release both managed and unmanaged resources; false to release only unmanaged resources. - protected virtual void Dispose(bool dispose) - { - if (dispose) - { - _installationManager.PackageInstallationCancelled -= OnPackageInstallationCancelled; - } - } - } -} diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallationCancelledNotifier.cs b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallationCancelledNotifier.cs new file mode 100644 index 0000000000..1c600683a9 --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallationCancelledNotifier.cs @@ -0,0 +1,31 @@ +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.Events.Updates; +using MediaBrowser.Controller.Session; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Updates +{ + /// + /// Notifies admin users when a plugin installation is cancelled. + /// + public class PluginInstallationCancelledNotifier : IEventConsumer + { + private readonly ISessionManager _sessionManager; + + /// + /// Initializes a new instance of the class. + /// + /// The session manager. + public PluginInstallationCancelledNotifier(ISessionManager sessionManager) + { + _sessionManager = sessionManager; + } + + /// + public async Task OnEvent(PluginInstallationCancelledEventArgs eventArgs) + { + await _sessionManager.SendMessageToAdminSessions("PackageInstallationCancelled", eventArgs.Argument, CancellationToken.None).ConfigureAwait(false); + } + } +} diff --git a/MediaBrowser.Controller/Events/Updates/PluginInstallationCancelledEventArgs.cs b/MediaBrowser.Controller/Events/Updates/PluginInstallationCancelledEventArgs.cs new file mode 100644 index 0000000000..b06046c05a --- /dev/null +++ b/MediaBrowser.Controller/Events/Updates/PluginInstallationCancelledEventArgs.cs @@ -0,0 +1,19 @@ +using Jellyfin.Data.Events; +using MediaBrowser.Model.Updates; + +namespace MediaBrowser.Controller.Events.Updates +{ + /// + /// An event that occurs when a plugin installation is cancelled. + /// + public class PluginInstallationCancelledEventArgs : GenericEventArgs + { + /// + /// Initializes a new instance of the class. + /// + /// The installation info. + public PluginInstallationCancelledEventArgs(InstallationInfo arg) : base(arg) + { + } + } +} -- cgit v1.2.3 From dcf97efaf8f24c8ee28c616c8f45263ccaa77b5c Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 15 Aug 2020 23:22:26 -0400 Subject: Rename PackageInstallationFailedLogger to have more consistent naming. --- .../Updates/PackageInstallationFailedLogger.cs | 51 ---------------------- .../Updates/PluginInstallationFailedLogger.cs | 51 ++++++++++++++++++++++ .../Events/EventingServiceCollectionExtensions.cs | 2 +- 3 files changed, 52 insertions(+), 52 deletions(-) delete mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Updates/PackageInstallationFailedLogger.cs create mode 100644 Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallationFailedLogger.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PackageInstallationFailedLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PackageInstallationFailedLogger.cs deleted file mode 100644 index 5d7296b3b7..0000000000 --- a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PackageInstallationFailedLogger.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.Globalization; -using System.Threading.Tasks; -using Jellyfin.Data.Entities; -using MediaBrowser.Common.Updates; -using MediaBrowser.Controller.Events; -using MediaBrowser.Model.Activity; -using MediaBrowser.Model.Globalization; -using MediaBrowser.Model.Notifications; - -namespace Jellyfin.Server.Implementations.Events.Consumers.Updates -{ - /// - /// Creates an entry in the activity log when a package installation fails. - /// - public class PackageInstallationFailedLogger : IEventConsumer - { - private readonly ILocalizationManager _localizationManager; - private readonly IActivityManager _activityManager; - - /// - /// Initializes a new instance of the class. - /// - /// The localization manager. - /// The activity manager. - public PackageInstallationFailedLogger(ILocalizationManager localizationManager, IActivityManager activityManager) - { - _localizationManager = localizationManager; - _activityManager = activityManager; - } - - /// - public async Task OnEvent(InstallationFailedEventArgs eventArgs) - { - await _activityManager.CreateAsync(new ActivityLog( - string.Format( - CultureInfo.InvariantCulture, - _localizationManager.GetLocalizedString("NameInstallFailed"), - eventArgs.InstallationInfo.Name), - NotificationType.InstallationFailed.ToString(), - Guid.Empty) - { - ShortOverview = string.Format( - CultureInfo.InvariantCulture, - _localizationManager.GetLocalizedString("VersionNumber"), - eventArgs.InstallationInfo.Version), - Overview = eventArgs.Exception.Message - }).ConfigureAwait(false); - } - } -} diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallationFailedLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallationFailedLogger.cs new file mode 100644 index 0000000000..d71c298c54 --- /dev/null +++ b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallationFailedLogger.cs @@ -0,0 +1,51 @@ +using System; +using System.Globalization; +using System.Threading.Tasks; +using Jellyfin.Data.Entities; +using MediaBrowser.Common.Updates; +using MediaBrowser.Controller.Events; +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.Notifications; + +namespace Jellyfin.Server.Implementations.Events.Consumers.Updates +{ + /// + /// Creates an entry in the activity log when a package installation fails. + /// + public class PluginInstallationFailedLogger : IEventConsumer + { + private readonly ILocalizationManager _localizationManager; + private readonly IActivityManager _activityManager; + + /// + /// Initializes a new instance of the class. + /// + /// The localization manager. + /// The activity manager. + public PluginInstallationFailedLogger(ILocalizationManager localizationManager, IActivityManager activityManager) + { + _localizationManager = localizationManager; + _activityManager = activityManager; + } + + /// + public async Task OnEvent(InstallationFailedEventArgs eventArgs) + { + await _activityManager.CreateAsync(new ActivityLog( + string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("NameInstallFailed"), + eventArgs.InstallationInfo.Name), + NotificationType.InstallationFailed.ToString(), + Guid.Empty) + { + ShortOverview = string.Format( + CultureInfo.InvariantCulture, + _localizationManager.GetLocalizedString("VersionNumber"), + eventArgs.InstallationInfo.Version), + Overview = eventArgs.Exception.Message + }).ConfigureAwait(false); + } + } +} diff --git a/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs b/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs index 84181f4fee..de9dc08afa 100644 --- a/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs +++ b/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs @@ -43,7 +43,7 @@ namespace Jellyfin.Server.Implementations.Events collection.AddScoped, PluginInstalledLogger>(); collection.AddScoped, PluginUninstalledLogger>(); collection.AddScoped, PluginUpdatedLogger>(); - collection.AddScoped, PackageInstallationFailedLogger>(); + collection.AddScoped, PluginInstallationFailedLogger>(); collection.AddScoped, UserCreatedLogger>(); collection.AddScoped, UserDeletedLogger>(); -- cgit v1.2.3 From 075ae53d831abdb4eb72aa7da575058a51d36753 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 15 Aug 2020 23:27:51 -0400 Subject: Register new IEventConsumer services. --- .../Events/EventingServiceCollectionExtensions.cs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs b/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs index de9dc08afa..517d4c27bd 100644 --- a/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs +++ b/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs @@ -40,10 +40,15 @@ namespace Jellyfin.Server.Implementations.Events collection.AddScoped, SessionStartedLogger>(); collection.AddScoped, SessionEndedLogger>(); + collection.AddScoped, PluginInstallingNotifier>(); collection.AddScoped, PluginInstalledLogger>(); + collection.AddScoped, PluginInstalledNotifier>(); collection.AddScoped, PluginUninstalledLogger>(); + collection.AddScoped, PluginUninstalledNotifier>(); collection.AddScoped, PluginUpdatedLogger>(); collection.AddScoped, PluginInstallationFailedLogger>(); + collection.AddScoped, PluginInstallationFailedNotifier>(); + collection.AddScoped, PluginInstallationCancelledNotifier>(); collection.AddScoped, UserCreatedLogger>(); collection.AddScoped, UserDeletedLogger>(); -- cgit v1.2.3 From 6f88087fa9ef27b6f052ee632c4dbf5f18b78b0b Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Mon, 17 Aug 2020 21:42:59 -0400 Subject: Use index access instead of LINQ. --- .../Events/Consumers/Session/PlaybackStartLogger.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStartLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStartLogger.cs index c48683ea38..ec4a76e7ff 100644 --- a/Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStartLogger.cs +++ b/Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStartLogger.cs @@ -1,6 +1,5 @@ using System; using System.Globalization; -using System.Linq; using System.Threading.Tasks; using Jellyfin.Data.Entities; using MediaBrowser.Controller.Events; @@ -56,7 +55,7 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Session return; } - var user = eventArgs.Users.First(); + var user = eventArgs.Users[0]; await _activityManager.CreateAsync(new ActivityLog( string.Format( -- cgit v1.2.3 From ee7beed804a23e1f4ef180ab17a0c99b47401caa Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Mon, 17 Aug 2020 21:47:49 -0400 Subject: Comment and reorder service registration. --- .../Events/EventingServiceCollectionExtensions.cs | 27 ++++++++++++++-------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs b/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs index 517d4c27bd..5d558189b1 100644 --- a/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs +++ b/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs @@ -1,4 +1,5 @@ using Jellyfin.Data.Events; +using Jellyfin.Data.Events.System; using Jellyfin.Data.Events.Users; using Jellyfin.Server.Implementations.Events.Consumers.Library; using Jellyfin.Server.Implementations.Events.Consumers.Security; @@ -30,34 +31,42 @@ namespace Jellyfin.Server.Implementations.Events /// The service collection. public static void AddEventServices(this IServiceCollection collection) { + // Library consumers collection.AddScoped, SubtitleDownloadFailureLogger>(); - collection.AddScoped>, AuthenticationSucceededLogger>(); + // Security consumers collection.AddScoped>, AuthenticationFailedLogger>(); + collection.AddScoped>, AuthenticationSucceededLogger>(); + // Session consumers collection.AddScoped, PlaybackStartLogger>(); collection.AddScoped, PlaybackStopLogger>(); - collection.AddScoped, SessionStartedLogger>(); collection.AddScoped, SessionEndedLogger>(); + collection.AddScoped, SessionStartedLogger>(); - collection.AddScoped, PluginInstallingNotifier>(); + // System consumers + collection.AddScoped, PendingRestartNotifier>(); + collection.AddScoped, TaskCompletedLogger>(); + collection.AddScoped, TaskCompletedNotifier>(); + + // Update consumers + collection.AddScoped, PluginInstallationCancelledNotifier>(); + collection.AddScoped, PluginInstallationFailedLogger>(); + collection.AddScoped, PluginInstallationFailedNotifier>(); collection.AddScoped, PluginInstalledLogger>(); collection.AddScoped, PluginInstalledNotifier>(); + collection.AddScoped, PluginInstallingNotifier>(); collection.AddScoped, PluginUninstalledLogger>(); collection.AddScoped, PluginUninstalledNotifier>(); collection.AddScoped, PluginUpdatedLogger>(); - collection.AddScoped, PluginInstallationFailedLogger>(); - collection.AddScoped, PluginInstallationFailedNotifier>(); - collection.AddScoped, PluginInstallationCancelledNotifier>(); + // User consumers collection.AddScoped, UserCreatedLogger>(); collection.AddScoped, UserDeletedLogger>(); collection.AddScoped, UserDeletedNotifier>(); - collection.AddScoped, UserUpdatedNotifier>(); collection.AddScoped, UserLockedOutLogger>(); collection.AddScoped, UserPasswordChangedLogger>(); - - collection.AddScoped, TaskCompletedLogger>(); + collection.AddScoped, UserUpdatedNotifier>(); } } } -- cgit v1.2.3 From fa8892fde4282906f4522f033aa88e15b4397a03 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Mon, 24 Aug 2020 20:27:10 -0400 Subject: Make LibraryController.GetDownload async --- Jellyfin.Api/Controllers/LibraryController.cs | 10 +++++----- Jellyfin.Server.Implementations/Activity/ActivityManager.cs | 10 ---------- MediaBrowser.Model/Activity/IActivityManager.cs | 2 -- 3 files changed, 5 insertions(+), 17 deletions(-) (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs index 4548e202a0..796d2d8aa0 100644 --- a/Jellyfin.Api/Controllers/LibraryController.cs +++ b/Jellyfin.Api/Controllers/LibraryController.cs @@ -619,7 +619,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.Download)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult GetDownload([FromRoute] Guid itemId) + public async Task GetDownload([FromRoute] Guid itemId) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -648,7 +648,7 @@ namespace Jellyfin.Api.Controllers if (user != null) { - LogDownload(item, user, auth); + await LogDownloadAsync(item, user, auth).ConfigureAwait(false); } var path = item.Path; @@ -861,17 +861,17 @@ namespace Jellyfin.Api.Controllers : item; } - private void LogDownload(BaseItem item, User user, AuthorizationInfo auth) + private async Task LogDownloadAsync(BaseItem item, User user, AuthorizationInfo auth) { try { - _activityManager.Create(new ActivityLog( + await _activityManager.CreateAsync(new ActivityLog( string.Format(CultureInfo.InvariantCulture, _localization.GetLocalizedString("UserDownloadingItemWithValues"), user.Username, item.Name), "UserDownloadingContent", auth.UserId) { ShortOverview = string.Format(CultureInfo.InvariantCulture, _localization.GetLocalizedString("AppDeviceValues"), auth.Client, auth.Device), - }); + }).ConfigureAwait(false); } catch { diff --git a/Jellyfin.Server.Implementations/Activity/ActivityManager.cs b/Jellyfin.Server.Implementations/Activity/ActivityManager.cs index 2deefbe819..bd285f6f15 100644 --- a/Jellyfin.Server.Implementations/Activity/ActivityManager.cs +++ b/Jellyfin.Server.Implementations/Activity/ActivityManager.cs @@ -27,16 +27,6 @@ namespace Jellyfin.Server.Implementations.Activity /// public event EventHandler> EntryCreated; - /// - public void Create(ActivityLog entry) - { - using var dbContext = _provider.CreateContext(); - dbContext.ActivityLogs.Add(entry); - dbContext.SaveChanges(); - - EntryCreated?.Invoke(this, new GenericEventArgs(ConvertToOldModel(entry))); - } - /// public async Task CreateAsync(ActivityLog entry) { diff --git a/MediaBrowser.Model/Activity/IActivityManager.cs b/MediaBrowser.Model/Activity/IActivityManager.cs index 9dab5e77b7..e5e7b0763c 100644 --- a/MediaBrowser.Model/Activity/IActivityManager.cs +++ b/MediaBrowser.Model/Activity/IActivityManager.cs @@ -13,8 +13,6 @@ namespace MediaBrowser.Model.Activity { event EventHandler> EntryCreated; - void Create(ActivityLog entry); - Task CreateAsync(ActivityLog entry); QueryResult GetPagedResult(int? startIndex, int? limit); -- cgit v1.2.3 From ec8967b8e6f201db84139c6ea96cc1769c2416ff Mon Sep 17 00:00:00 2001 From: crobibero Date: Thu, 27 Aug 2020 10:00:06 -0600 Subject: Fix partial library and channel access --- Jellyfin.Server.Implementations/Users/UserManager.cs | 12 ++++++------ Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs | 6 ++++-- MediaBrowser.Model/Users/UserPolicy.cs | 12 ++++++------ 3 files changed, 16 insertions(+), 14 deletions(-) (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index 3e8edeb442..8f04baa089 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -402,13 +402,13 @@ namespace Jellyfin.Server.Implementations.Users EnablePublicSharing = user.HasPermission(PermissionKind.EnablePublicSharing), AccessSchedules = user.AccessSchedules.ToArray(), BlockedTags = user.GetPreference(PreferenceKind.BlockedTags), - EnabledChannels = user.GetPreference(PreferenceKind.EnabledChannels), + EnabledChannels = user.GetPreference(PreferenceKind.EnabledChannels)?.Select(Guid.Parse).ToArray(), EnabledDevices = user.GetPreference(PreferenceKind.EnabledDevices), - EnabledFolders = user.GetPreference(PreferenceKind.EnabledFolders), + EnabledFolders = user.GetPreference(PreferenceKind.EnabledFolders)?.Select(Guid.Parse).ToArray(), EnableContentDeletionFromFolders = user.GetPreference(PreferenceKind.EnableContentDeletionFromFolders), SyncPlayAccess = user.SyncPlayAccess, - BlockedChannels = user.GetPreference(PreferenceKind.BlockedChannels), - BlockedMediaFolders = user.GetPreference(PreferenceKind.BlockedMediaFolders), + BlockedChannels = user.GetPreference(PreferenceKind.BlockedChannels)?.Select(Guid.Parse).ToArray(), + BlockedMediaFolders = user.GetPreference(PreferenceKind.BlockedMediaFolders)?.Select(Guid.Parse).ToArray(), BlockUnratedItems = user.GetPreference(PreferenceKind.BlockUnratedItems).Select(Enum.Parse).ToArray() } }; @@ -735,9 +735,9 @@ namespace Jellyfin.Server.Implementations.Users PreferenceKind.BlockUnratedItems, policy.BlockUnratedItems?.Select(i => i.ToString()).ToArray() ?? Array.Empty()); user.SetPreference(PreferenceKind.BlockedTags, policy.BlockedTags); - user.SetPreference(PreferenceKind.EnabledChannels, policy.EnabledChannels); + user.SetPreference(PreferenceKind.EnabledChannels, policy.EnabledChannels?.Select(i => i.ToString("N", CultureInfo.InvariantCulture)).ToArray()); user.SetPreference(PreferenceKind.EnabledDevices, policy.EnabledDevices); - user.SetPreference(PreferenceKind.EnabledFolders, policy.EnabledFolders); + user.SetPreference(PreferenceKind.EnabledFolders, policy.EnabledFolders?.Select(i => i.ToString("N", CultureInfo.InvariantCulture)).ToArray()); user.SetPreference(PreferenceKind.EnableContentDeletionFromFolders, policy.EnableContentDeletionFromFolders); dbContext.Update(user); diff --git a/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs index ac6890f386..74c5503314 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs @@ -1,5 +1,7 @@ using System; +using System.Globalization; using System.IO; +using System.Linq; using Emby.Server.Implementations.Data; using Emby.Server.Implementations.Serialization; using Jellyfin.Data.Entities; @@ -166,9 +168,9 @@ namespace Jellyfin.Server.Migrations.Routines } user.SetPreference(PreferenceKind.BlockedTags, policy.BlockedTags); - user.SetPreference(PreferenceKind.EnabledChannels, policy.EnabledChannels); + user.SetPreference(PreferenceKind.EnabledChannels, policy.EnabledChannels?.Select(i => i.ToString("N", CultureInfo.InvariantCulture)).ToArray()); user.SetPreference(PreferenceKind.EnabledDevices, policy.EnabledDevices); - user.SetPreference(PreferenceKind.EnabledFolders, policy.EnabledFolders); + user.SetPreference(PreferenceKind.EnabledFolders, policy.EnabledFolders?.Select(i => i.ToString("N", CultureInfo.InvariantCulture)).ToArray()); user.SetPreference(PreferenceKind.EnableContentDeletionFromFolders, policy.EnableContentDeletionFromFolders); user.SetPreference(PreferenceKind.OrderedViews, config.OrderedViews); user.SetPreference(PreferenceKind.GroupedFolders, config.GroupedFolders); diff --git a/MediaBrowser.Model/Users/UserPolicy.cs b/MediaBrowser.Model/Users/UserPolicy.cs index caf2e0f549..a1f01f7e8e 100644 --- a/MediaBrowser.Model/Users/UserPolicy.cs +++ b/MediaBrowser.Model/Users/UserPolicy.cs @@ -80,11 +80,11 @@ namespace MediaBrowser.Model.Users public bool EnableAllDevices { get; set; } - public string[] EnabledChannels { get; set; } + public Guid[] EnabledChannels { get; set; } public bool EnableAllChannels { get; set; } - public string[] EnabledFolders { get; set; } + public Guid[] EnabledFolders { get; set; } public bool EnableAllFolders { get; set; } @@ -94,9 +94,9 @@ namespace MediaBrowser.Model.Users public bool EnablePublicSharing { get; set; } - public string[] BlockedMediaFolders { get; set; } + public Guid[] BlockedMediaFolders { get; set; } - public string[] BlockedChannels { get; set; } + public Guid[] BlockedChannels { get; set; } public int RemoteClientBitrateLimit { get; set; } @@ -145,10 +145,10 @@ namespace MediaBrowser.Model.Users LoginAttemptsBeforeLockout = -1; EnableAllChannels = true; - EnabledChannels = Array.Empty(); + EnabledChannels = Array.Empty(); EnableAllFolders = true; - EnabledFolders = Array.Empty(); + EnabledFolders = Array.Empty(); EnabledDevices = Array.Empty(); EnableAllDevices = true; -- cgit v1.2.3 From acb213e4b8edf1c55f615fa8d0079f0fb7fdea68 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sun, 30 Aug 2020 18:50:54 -0400 Subject: First pass at cleaning entity classes. - Documents all library entities - Fixes styling warnings for library entities - Updates library entities to inherit from interfaces - Makes library entites no longer partial. --- Jellyfin.Data/Entities/ActivityLog.cs | 3 +- Jellyfin.Data/Entities/Group.cs | 3 +- Jellyfin.Data/Entities/Libraries/Artwork.cs | 203 ++--------- Jellyfin.Data/Entities/Libraries/Book.cs | 62 +--- Jellyfin.Data/Entities/Libraries/BookMetadata.cs | 120 ++----- Jellyfin.Data/Entities/Libraries/Chapter.cs | 257 +++----------- Jellyfin.Data/Entities/Libraries/Collection.cs | 112 ++---- Jellyfin.Data/Entities/Libraries/CollectionItem.cs | 152 +++----- Jellyfin.Data/Entities/Libraries/Company.cs | 156 ++------ .../Entities/Libraries/CompanyMetadata.cs | 226 ++---------- Jellyfin.Data/Entities/Libraries/CustomItem.cs | 61 +--- .../Entities/Libraries/CustomItemMetadata.cs | 77 +--- Jellyfin.Data/Entities/Libraries/Episode.cs | 114 ++---- .../Entities/Libraries/EpisodeMetadata.cs | 191 ++-------- Jellyfin.Data/Entities/Libraries/Genre.cs | 147 ++------ Jellyfin.Data/Entities/Libraries/Library.cs | 143 ++------ Jellyfin.Data/Entities/Libraries/LibraryItem.cs | 164 ++------- Jellyfin.Data/Entities/Libraries/LibraryRoot.cs | 199 ----------- Jellyfin.Data/Entities/Libraries/MediaFile.cs | 200 +++-------- .../Entities/Libraries/MediaFileStream.cs | 144 ++------ Jellyfin.Data/Entities/Libraries/Metadata.cs | 392 +++++---------------- .../Entities/Libraries/MetadataProvider.cs | 134 ++----- .../Entities/Libraries/MetadataProviderId.cs | 194 ++-------- Jellyfin.Data/Entities/Libraries/Movie.cs | 64 +--- Jellyfin.Data/Entities/Libraries/MovieMetadata.cs | 249 +++---------- Jellyfin.Data/Entities/Libraries/MusicAlbum.cs | 60 +--- .../Entities/Libraries/MusicAlbumMetadata.cs | 204 ++--------- Jellyfin.Data/Entities/Libraries/Person.cs | 308 +++------------- Jellyfin.Data/Entities/Libraries/PersonRole.cs | 215 +++-------- Jellyfin.Data/Entities/Libraries/Photo.cs | 61 +--- Jellyfin.Data/Entities/Libraries/PhotoMetadata.cs | 79 +---- Jellyfin.Data/Entities/Libraries/Rating.cs | 186 ++-------- Jellyfin.Data/Entities/Libraries/RatingSource.cs | 227 +++--------- Jellyfin.Data/Entities/Libraries/Release.cs | 211 ++--------- Jellyfin.Data/Entities/Libraries/Season.cs | 114 ++---- Jellyfin.Data/Entities/Libraries/SeasonMetadata.cs | 115 ++---- Jellyfin.Data/Entities/Libraries/Series.cs | 153 +------- Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs | 241 +++---------- Jellyfin.Data/Entities/Libraries/Track.cs | 116 ++---- Jellyfin.Data/Entities/Libraries/TrackMetadata.cs | 77 +--- Jellyfin.Data/Entities/Permission.cs | 3 +- Jellyfin.Data/Entities/Preference.cs | 3 +- Jellyfin.Data/Entities/User.cs | 3 +- Jellyfin.Data/IHasPermissions.cs | 31 -- Jellyfin.Data/ISavingChanges.cs | 9 - Jellyfin.Data/Interfaces/IHasArtwork.cs | 16 + Jellyfin.Data/Interfaces/IHasCompanies.cs | 16 + Jellyfin.Data/Interfaces/IHasConcurrencyToken.cs | 18 + Jellyfin.Data/Interfaces/IHasPermissions.cs | 31 ++ Jellyfin.Data/Interfaces/IHasReleases.cs | 16 + Jellyfin.Server.Implementations/JellyfinDb.cs | 4 +- 51 files changed, 1203 insertions(+), 5081 deletions(-) delete mode 100644 Jellyfin.Data/Entities/Libraries/LibraryRoot.cs delete mode 100644 Jellyfin.Data/IHasPermissions.cs delete mode 100644 Jellyfin.Data/ISavingChanges.cs create mode 100644 Jellyfin.Data/Interfaces/IHasArtwork.cs create mode 100644 Jellyfin.Data/Interfaces/IHasCompanies.cs create mode 100644 Jellyfin.Data/Interfaces/IHasConcurrencyToken.cs create mode 100644 Jellyfin.Data/Interfaces/IHasPermissions.cs create mode 100644 Jellyfin.Data/Interfaces/IHasReleases.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Data/Entities/ActivityLog.cs b/Jellyfin.Data/Entities/ActivityLog.cs index ac61b9e3ba..3858916d15 100644 --- a/Jellyfin.Data/Entities/ActivityLog.cs +++ b/Jellyfin.Data/Entities/ActivityLog.cs @@ -3,6 +3,7 @@ using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; using Microsoft.Extensions.Logging; namespace Jellyfin.Data.Entities @@ -10,7 +11,7 @@ namespace Jellyfin.Data.Entities /// /// An entity referencing an activity log entry. /// - public partial class ActivityLog : ISavingChanges + public partial class ActivityLog : IHasConcurrencyToken { /// /// Initializes a new instance of the class. diff --git a/Jellyfin.Data/Entities/Group.cs b/Jellyfin.Data/Entities/Group.cs index a1ec6b1fa4..ca12ba4213 100644 --- a/Jellyfin.Data/Entities/Group.cs +++ b/Jellyfin.Data/Entities/Group.cs @@ -6,13 +6,14 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using Jellyfin.Data.Enums; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities { /// /// An entity representing a group. /// - public partial class Group : IHasPermissions, ISavingChanges + public partial class Group : IHasPermissions, IHasConcurrencyToken { /// /// Initializes a new instance of the class. diff --git a/Jellyfin.Data/Entities/Libraries/Artwork.cs b/Jellyfin.Data/Entities/Libraries/Artwork.cs index 2a34a8dff1..7be22af254 100644 --- a/Jellyfin.Data/Entities/Libraries/Artwork.cs +++ b/Jellyfin.Data/Entities/Libraries/Artwork.cs @@ -1,210 +1,81 @@ -#pragma warning disable CS1591 - using System; using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Enums; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class Artwork + /// + /// An entity representing artwork. + /// + public class Artwork : IHasConcurrencyToken { - partial void Init(); - - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. - /// - protected Artwork() - { - Init(); - } - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. + /// Initializes a new instance of the class. /// - public static Artwork CreateArtworkUnsafe() - { - return new Artwork(); - } - - /// - /// Public constructor with required data. - /// - /// - /// - /// - /// - public Artwork(string path, Enums.ArtKind kind, Metadata _metadata0, PersonRole _personrole1) + /// The path. + /// The kind of art. + /// The owner. + public Artwork(string path, ArtKind kind, IHasArtwork owner) { if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException(nameof(path)); } - this.Path = path; - - this.Kind = kind; - - if (_metadata0 == null) - { - throw new ArgumentNullException(nameof(_metadata0)); - } - - _metadata0.Artwork.Add(this); + Path = path; + Kind = kind; - if (_personrole1 == null) - { - throw new ArgumentNullException(nameof(_personrole1)); - } - - _personrole1.Artwork = this; - - Init(); + owner?.Artwork.Add(this); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// - /// - /// - /// - public static Artwork Create(string path, Enums.ArtKind kind, Metadata _metadata0, PersonRole _personrole1) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected Artwork() { - return new Artwork(path, kind, _metadata0, _personrole1); } - /************************************************************************* - * Properties - *************************************************************************/ - /// - /// Backing field for Id. + /// Gets or sets the id. /// - internal int _Id; - /// - /// When provided in a partial class, allows value of Id to be changed before setting. - /// - partial void SetId(int oldValue, ref int newValue); - /// - /// When provided in a partial class, allows value of Id to be changed before returning. - /// - partial void GetId(ref int result); - - /// + /// /// Identity, Indexed, Required. - /// - [Key] - [Required] - public int Id - { - get - { - int value = _Id; - GetId(ref value); - return _Id = value; - } - - protected set - { - int oldValue = _Id; - SetId(oldValue, ref value); - if (oldValue != value) - { - _Id = value; - } - } - } - - /// - /// Backing field for Path. - /// - protected string _Path; - /// - /// When provided in a partial class, allows value of Path to be changed before setting. - /// - partial void SetPath(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Path to be changed before returning. - /// - partial void GetPath(ref string result); + /// + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; protected set; } /// - /// Required, Max length = 65535 + /// Gets or sets the path. /// + /// + /// Required, Max length = 65535. + /// [Required] [MaxLength(65535)] [StringLength(65535)] - public string Path - { - get - { - string value = _Path; - GetPath(ref value); - return _Path = value; - } + public string Path { get; set; } - set - { - string oldValue = _Path; - SetPath(oldValue, ref value); - if (oldValue != value) - { - _Path = value; - } - } - } - - /// - /// Backing field for Kind. - /// - internal Enums.ArtKind _Kind; /// - /// When provided in a partial class, allows value of Kind to be changed before setting. + /// Gets or sets the kind of artwork. /// - partial void SetKind(Enums.ArtKind oldValue, ref Enums.ArtKind newValue); - /// - /// When provided in a partial class, allows value of Kind to be changed before returning. - /// - partial void GetKind(ref Enums.ArtKind result); - - /// - /// Indexed, Required. - /// - [Required] - public Enums.ArtKind Kind - { - get - { - Enums.ArtKind value = _Kind; - GetKind(ref value); - return _Kind = value; - } + /// + /// Required. + /// + public ArtKind Kind { get; set; } - set - { - Enums.ArtKind oldValue = _Kind; - SetKind(oldValue, ref value); - if (oldValue != value) - { - _Kind = value; - } - } - } - - /// - /// Required, ConcurrenyToken. - /// + /// [ConcurrencyCheck] - [Required] public uint RowVersion { get; set; } + /// public void OnSavingChanges() { RowVersion++; } - - /************************************************************************* - * Navigation properties - *************************************************************************/ } } - diff --git a/Jellyfin.Data/Entities/Libraries/Book.cs b/Jellyfin.Data/Entities/Libraries/Book.cs index 1ddc5ce8b1..8337788ddd 100644 --- a/Jellyfin.Data/Entities/Libraries/Book.cs +++ b/Jellyfin.Data/Entities/Libraries/Book.cs @@ -1,72 +1,28 @@ -#pragma warning disable CS1591 - -using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class Book : LibraryItem + /// + /// An entity representing a book. + /// + public class Book : LibraryItem, IHasReleases { - partial void Init(); - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. + /// Initializes a new instance of the class. /// - protected Book() + public Book() { BookMetadata = new HashSet(); Releases = new HashSet(); - - Init(); } /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. + /// Gets or sets a collection containing the metadata for this book. /// - public static Book CreateBookUnsafe() - { - return new Book(); - } - - /// - /// Public constructor with required data. - /// - /// This is whats gets displayed in the Urls and API requests. This could also be a string. - /// The date the object was added. - public Book(Guid urlid, DateTime dateadded) - { - this.UrlId = urlid; - - this.BookMetadata = new HashSet(); - this.Releases = new HashSet(); - - Init(); - } - - /// - /// Static create function (for use in LINQ queries, etc.) - /// - /// This is whats gets displayed in the Urls and API requests. This could also be a string. - /// The date the object was added. - public static Book Create(Guid urlid, DateTime dateadded) - { - return new Book(urlid, dateadded); - } - - /************************************************************************* - * Properties - *************************************************************************/ - - /************************************************************************* - * Navigation properties - *************************************************************************/ - - [ForeignKey("BookMetadata_BookMetadata_Id")] public virtual ICollection BookMetadata { get; protected set; } - [ForeignKey("Release_Releases_Id")] + /// public virtual ICollection Releases { get; protected set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/BookMetadata.cs b/Jellyfin.Data/Entities/Libraries/BookMetadata.cs index 91eecbbf99..bd716712b1 100644 --- a/Jellyfin.Data/Entities/Libraries/BookMetadata.cs +++ b/Jellyfin.Data/Entities/Libraries/BookMetadata.cs @@ -1,125 +1,55 @@ -#pragma warning disable CS1591 - using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class BookMetadata : Metadata + /// + /// An entity containing metadata for a book. + /// + public class BookMetadata : Metadata, IHasCompanies { - partial void Init(); - - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. - /// - protected BookMetadata() - { - Publishers = new HashSet(); - - Init(); - } - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static BookMetadata CreateBookMetadataUnsafe() - { - return new BookMetadata(); - } - - /// - /// Public constructor with required data. + /// Initializes a new instance of the class. /// /// The title or name of the object. /// ISO-639-3 3-character language codes. - /// The date the object was added. - /// The date the object was last modified. - /// - public BookMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Book _book0) + /// The book. + public BookMetadata(string title, string language, Book book) : base(title, language) { - if (string.IsNullOrEmpty(title)) - { - throw new ArgumentNullException(nameof(title)); - } - - this.Title = title; - - if (string.IsNullOrEmpty(language)) - { - throw new ArgumentNullException(nameof(language)); - } - - this.Language = language; - - if (_book0 == null) + if (book == null) { - throw new ArgumentNullException(nameof(_book0)); + throw new ArgumentNullException(nameof(book)); } - _book0.BookMetadata.Add(this); - - this.Publishers = new HashSet(); + book.BookMetadata.Add(this); - Init(); + Publishers = new HashSet(); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// The title or name of the object. - /// ISO-639-3 3-character language codes. - /// The date the object was added. - /// The date the object was last modified. - /// - public static BookMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, Book _book0) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected BookMetadata() { - return new BookMetadata(title, language, dateadded, datemodified, _book0); } - /************************************************************************* - * Properties - *************************************************************************/ - - /// - /// Backing field for ISBN. - /// - protected long? _ISBN; /// - /// When provided in a partial class, allows value of ISBN to be changed before setting. + /// Gets or sets the ISBN. /// - partial void SetISBN(long? oldValue, ref long? newValue); + public long? Isbn { get; set; } + /// - /// When provided in a partial class, allows value of ISBN to be changed before returning. + /// Gets or sets a collection of the publishers for this book. /// - partial void GetISBN(ref long? result); - - public long? ISBN - { - get - { - long? value = _ISBN; - GetISBN(ref value); - return _ISBN = value; - } - - set - { - long? oldValue = _ISBN; - SetISBN(oldValue, ref value); - if (oldValue != value) - { - _ISBN = value; - } - } - } - - /************************************************************************* - * Navigation properties - *************************************************************************/ - - [ForeignKey("Company_Publishers_Id")] public virtual ICollection Publishers { get; protected set; } + + /// + [NotMapped] + public ICollection Companies => Publishers; } } - diff --git a/Jellyfin.Data/Entities/Libraries/Chapter.cs b/Jellyfin.Data/Entities/Libraries/Chapter.cs index 2f36443183..d9293c3cc4 100644 --- a/Jellyfin.Data/Entities/Libraries/Chapter.cs +++ b/Jellyfin.Data/Entities/Libraries/Chapter.cs @@ -1,277 +1,102 @@ -#pragma warning disable CS1591 - using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class Chapter + /// + /// An entity representing a chapter. + /// + public class Chapter : IHasConcurrencyToken { - partial void Init(); - - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. - /// - protected Chapter() - { - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static Chapter CreateChapterUnsafe() - { - return new Chapter(); - } - /// - /// Public constructor with required data. + /// Initializes a new instance of the class. /// /// ISO-639-3 3-character language codes. - /// - /// - public Chapter(string language, long timestart, Release _release0) + /// The start time for this chapter. + /// The release. + public Chapter(string language, long startTime, Release release) { if (string.IsNullOrEmpty(language)) { throw new ArgumentNullException(nameof(language)); } - this.Language = language; - - this.TimeStart = timestart; + Language = language; + StartTime = startTime; - if (_release0 == null) + if (release == null) { - throw new ArgumentNullException(nameof(_release0)); + throw new ArgumentNullException(nameof(release)); } - _release0.Chapters.Add(this); - - - Init(); + release.Chapters.Add(this); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// ISO-639-3 3-character language codes. - /// - /// - public static Chapter Create(string language, long timestart, Release _release0) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected Chapter() { - return new Chapter(language, timestart, _release0); } - /************************************************************************* - * Properties - *************************************************************************/ - - /// - /// Backing field for Id. - /// - internal int _Id; - /// - /// When provided in a partial class, allows value of Id to be changed before setting. - /// - partial void SetId(int oldValue, ref int newValue); /// - /// When provided in a partial class, allows value of Id to be changed before returning. + /// Gets or sets the id. /// - partial void GetId(ref int result); - - /// + /// /// Identity, Indexed, Required. - /// - [Key] - [Required] + /// [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public int Id - { - get - { - int value = _Id; - GetId(ref value); - return _Id = value; - } - - protected set - { - int oldValue = _Id; - SetId(oldValue, ref value); - if (oldValue != value) - { - _Id = value; - } - } - } + public int Id { get; protected set; } /// - /// Backing field for Name. - /// - protected string _Name; - /// - /// When provided in a partial class, allows value of Name to be changed before setting. - /// - partial void SetName(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Name to be changed before returning. - /// - partial void GetName(ref string result); - - /// - /// Max length = 1024 + /// Gets or sets the name. /// + /// + /// Max length = 1024. + /// [MaxLength(1024)] [StringLength(1024)] - public string Name - { - get - { - string value = _Name; - GetName(ref value); - return _Name = value; - } - - set - { - string oldValue = _Name; - SetName(oldValue, ref value); - if (oldValue != value) - { - _Name = value; - } - } - } + public string Name { get; set; } /// - /// Backing field for Language. - /// - protected string _Language; - /// - /// When provided in a partial class, allows value of Language to be changed before setting. - /// - partial void SetLanguage(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Language to be changed before returning. + /// Gets or sets the language. /// - partial void GetLanguage(ref string result); - - /// + /// /// Required, Min length = 3, Max length = 3 /// ISO-639-3 3-character language codes. - /// + /// [Required] [MinLength(3)] [MaxLength(3)] [StringLength(3)] - public string Language - { - get - { - string value = _Language; - GetLanguage(ref value); - return _Language = value; - } + public string Language { get; set; } - set - { - string oldValue = _Language; - SetLanguage(oldValue, ref value); - if (oldValue != value) - { - _Language = value; - } - } - } - - /// - /// Backing field for TimeStart. - /// - protected long _TimeStart; /// - /// When provided in a partial class, allows value of TimeStart to be changed before setting. + /// Gets or sets the start time. /// - partial void SetTimeStart(long oldValue, ref long newValue); - /// - /// When provided in a partial class, allows value of TimeStart to be changed before returning. - /// - partial void GetTimeStart(ref long result); - - /// + /// /// Required. - /// - [Required] - public long TimeStart - { - get - { - long value = _TimeStart; - GetTimeStart(ref value); - return _TimeStart = value; - } - - set - { - long oldValue = _TimeStart; - SetTimeStart(oldValue, ref value); - if (oldValue != value) - { - _TimeStart = value; - } - } - } + /// + public long StartTime { get; set; } /// - /// Backing field for TimeEnd. - /// - protected long? _TimeEnd; - /// - /// When provided in a partial class, allows value of TimeEnd to be changed before setting. + /// Gets or sets the end time. /// - partial void SetTimeEnd(long? oldValue, ref long? newValue); - /// - /// When provided in a partial class, allows value of TimeEnd to be changed before returning. - /// - partial void GetTimeEnd(ref long? result); - - public long? TimeEnd - { - get - { - long? value = _TimeEnd; - GetTimeEnd(ref value); - return _TimeEnd = value; - } - - set - { - long? oldValue = _TimeEnd; - SetTimeEnd(oldValue, ref value); - if (oldValue != value) - { - _TimeEnd = value; - } - } - } + public long? EndTime { get; set; } - /// - /// Required, ConcurrenyToken. - /// + /// [ConcurrencyCheck] - [Required] - public uint RowVersion { get; set; } + public uint RowVersion { get; protected set; } + /// public void OnSavingChanges() { RowVersion++; } - - /************************************************************************* - * Navigation properties - *************************************************************************/ } } - diff --git a/Jellyfin.Data/Entities/Libraries/Collection.cs b/Jellyfin.Data/Entities/Libraries/Collection.cs index d054d8ff99..2e1bbcfb60 100644 --- a/Jellyfin.Data/Entities/Libraries/Collection.cs +++ b/Jellyfin.Data/Entities/Libraries/Collection.cs @@ -1,123 +1,55 @@ -#pragma warning disable CS1591 - using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class Collection + /// + /// An entity representing a collection. + /// + public class Collection : IHasConcurrencyToken { - partial void Init(); - /// - /// Default constructor. + /// Initializes a new instance of the class. /// public Collection() { - CollectionItem = new LinkedList(); - - Init(); + Items = new HashSet(); } - /************************************************************************* - * Properties - *************************************************************************/ - - /// - /// Backing field for Id. - /// - internal int _Id; - /// - /// When provided in a partial class, allows value of Id to be changed before setting. - /// - partial void SetId(int oldValue, ref int newValue); /// - /// When provided in a partial class, allows value of Id to be changed before returning. + /// Gets or sets the id. /// - partial void GetId(ref int result); - - /// + /// /// Identity, Indexed, Required. - /// - [Key] - [Required] + /// [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public int Id - { - get - { - int value = _Id; - GetId(ref value); - return _Id = value; - } - - protected set - { - int oldValue = _Id; - SetId(oldValue, ref value); - if (oldValue != value) - { - _Id = value; - } - } - } + public int Id { get; protected set; } /// - /// Backing field for Name. - /// - protected string _Name; - /// - /// When provided in a partial class, allows value of Name to be changed before setting. - /// - partial void SetName(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Name to be changed before returning. - /// - partial void GetName(ref string result); - - /// - /// Max length = 1024 + /// Gets or sets the name. /// + /// + /// Max length = 1024. + /// [MaxLength(1024)] [StringLength(1024)] - public string Name - { - get - { - string value = _Name; - GetName(ref value); - return _Name = value; - } + public string Name { get; set; } - set - { - string oldValue = _Name; - SetName(oldValue, ref value); - if (oldValue != value) - { - _Name = value; - } - } - } + /// + [ConcurrencyCheck] + public uint RowVersion { get; set; } /// - /// Required, ConcurrenyToken. + /// Gets or sets a collection containing this collection's items. /// - [ConcurrencyCheck] - [Required] - public uint RowVersion { get; set; } + public virtual ICollection Items { get; protected set; } + /// public void OnSavingChanges() { RowVersion++; } - - /************************************************************************* - * Navigation properties - *************************************************************************/ - [ForeignKey("CollectionItem_CollectionItem_Id")] - public virtual ICollection CollectionItem { get; protected set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/CollectionItem.cs b/Jellyfin.Data/Entities/Libraries/CollectionItem.cs index 4b01d814fb..c9306f630a 100644 --- a/Jellyfin.Data/Entities/Libraries/CollectionItem.cs +++ b/Jellyfin.Data/Entities/Libraries/CollectionItem.cs @@ -1,156 +1,94 @@ -#pragma warning disable CS1591 - using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class CollectionItem + /// + /// An entity representing a collection item. + /// + public class CollectionItem : IHasConcurrencyToken { - partial void Init(); - - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. - /// - protected CollectionItem() - { - // NOTE: This class has one-to-one associations with CollectionItem. - // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other. - - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static CollectionItem CreateCollectionItemUnsafe() - { - return new CollectionItem(); - } - /// - /// Public constructor with required data. + /// Initializes a new instance of the class. /// - /// - /// - /// - public CollectionItem(Collection _collection0, CollectionItem _collectionitem1, CollectionItem _collectionitem2) + /// The collection. + /// The previous item. + /// The next item. + public CollectionItem(Collection collection, CollectionItem previous, CollectionItem next) { - // NOTE: This class has one-to-one associations with CollectionItem. - // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other. - - if (_collection0 == null) + if (collection == null) { - throw new ArgumentNullException(nameof(_collection0)); + throw new ArgumentNullException(nameof(collection)); } - _collection0.CollectionItem.Add(this); + collection.Items.Add(this); - if (_collectionitem1 == null) + if (next != null) { - throw new ArgumentNullException(nameof(_collectionitem1)); + Next = next; + next.Previous = this; } - _collectionitem1.Next = this; - - if (_collectionitem2 == null) + if (previous != null) { - throw new ArgumentNullException(nameof(_collectionitem2)); + Previous = previous; + previous.Next = this; } - - _collectionitem2.Previous = this; - - Init(); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// - /// - /// - public static CollectionItem Create(Collection _collection0, CollectionItem _collectionitem1, CollectionItem _collectionitem2) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected CollectionItem() { - return new CollectionItem(_collection0, _collectionitem1, _collectionitem2); } - /************************************************************************* - * Properties - *************************************************************************/ - /// - /// Backing field for Id. + /// Gets or sets the id. /// - internal int _Id; - /// - /// When provided in a partial class, allows value of Id to be changed before setting. - /// - partial void SetId(int oldValue, ref int newValue); - /// - /// When provided in a partial class, allows value of Id to be changed before returning. - /// - partial void GetId(ref int result); - - /// + /// /// Identity, Indexed, Required. - /// - [Key] - [Required] + /// [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public int Id - { - get - { - int value = _Id; - GetId(ref value); - return _Id = value; - } - - protected set - { - int oldValue = _Id; - SetId(oldValue, ref value); - if (oldValue != value) - { - _Id = value; - } - } - } + public int Id { get; set; } - /// - /// Required, ConcurrenyToken. - /// + /// [ConcurrencyCheck] - [Required] public uint RowVersion { get; set; } - public void OnSavingChanges() - { - RowVersion++; - } - - /************************************************************************* - * Navigation properties - *************************************************************************/ - /// - /// Required. + /// Gets or sets the library item. /// - [ForeignKey("LibraryItem_Id")] + /// + /// Required. + /// public virtual LibraryItem LibraryItem { get; set; } + /// + /// Gets or sets the next item in the collection. + /// /// /// TODO check if this properly updated dependant and has the proper principal relationship /// - [ForeignKey("CollectionItem_Next_Id")] public virtual CollectionItem Next { get; set; } + /// + /// Gets or sets the previous item in the collection. + /// /// /// TODO check if this properly updated dependant and has the proper principal relationship /// - [ForeignKey("CollectionItem_Previous_Id")] public virtual CollectionItem Previous { get; set; } + + /// + public void OnSavingChanges() + { + RowVersion++; + } } } - diff --git a/Jellyfin.Data/Entities/Libraries/Company.cs b/Jellyfin.Data/Entities/Libraries/Company.cs index 10df429cd7..02da26bc22 100644 --- a/Jellyfin.Data/Entities/Libraries/Company.cs +++ b/Jellyfin.Data/Entities/Libraries/Company.cs @@ -1,159 +1,67 @@ -#pragma warning disable CS1591 - -using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class Company + /// + /// An entity representing a company. + /// + public class Company : IHasCompanies, IHasConcurrencyToken { - partial void Init(); - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. + /// Initializes a new instance of the class. /// - protected Company() + /// The owner of this company. + public Company(IHasCompanies owner) { - CompanyMetadata = new HashSet(); - - Init(); - } + owner?.Companies.Add(this); - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static Company CreateCompanyUnsafe() - { - return new Company(); + CompanyMetadata = new HashSet(); } /// - /// Public constructor with required data. + /// Initializes a new instance of the class. /// - /// - /// - /// - /// - /// - public Company(MovieMetadata _moviemetadata0, SeriesMetadata _seriesmetadata1, MusicAlbumMetadata _musicalbummetadata2, BookMetadata _bookmetadata3, Company _company4) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected Company() { - if (_moviemetadata0 == null) - { - throw new ArgumentNullException(nameof(_moviemetadata0)); - } - - _moviemetadata0.Studios.Add(this); - - if (_seriesmetadata1 == null) - { - throw new ArgumentNullException(nameof(_seriesmetadata1)); - } - - _seriesmetadata1.Networks.Add(this); - - if (_musicalbummetadata2 == null) - { - throw new ArgumentNullException(nameof(_musicalbummetadata2)); - } - - _musicalbummetadata2.Labels.Add(this); - - if (_bookmetadata3 == null) - { - throw new ArgumentNullException(nameof(_bookmetadata3)); - } - - _bookmetadata3.Publishers.Add(this); - - if (_company4 == null) - { - throw new ArgumentNullException(nameof(_company4)); - } - - _company4.Parent = this; - - this.CompanyMetadata = new HashSet(); - - Init(); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Gets or sets the id. /// - /// - /// - /// - /// - /// - public static Company Create(MovieMetadata _moviemetadata0, SeriesMetadata _seriesmetadata1, MusicAlbumMetadata _musicalbummetadata2, BookMetadata _bookmetadata3, Company _company4) - { - return new Company(_moviemetadata0, _seriesmetadata1, _musicalbummetadata2, _bookmetadata3, _company4); - } + /// + /// Identity, Indexed, Required. + /// + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; protected set; } - /************************************************************************* - * Properties - *************************************************************************/ + /// + [ConcurrencyCheck] + public uint RowVersion { get; set; } /// - /// Backing field for Id. + /// Gets or sets a collection containing the metadata. /// - internal int _Id; - /// - /// When provided in a partial class, allows value of Id to be changed before setting. - /// - partial void SetId(int oldValue, ref int newValue); - /// - /// When provided in a partial class, allows value of Id to be changed before returning. - /// - partial void GetId(ref int result); + public virtual ICollection CompanyMetadata { get; protected set; } /// - /// Identity, Indexed, Required. + /// Gets or sets a collection containing this company's child companies. /// - [Key] - [Required] - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public int Id - { - get - { - int value = _Id; - GetId(ref value); - return _Id = value; - } + public virtual ICollection ChildCompanies { get; protected set; } - protected set - { - int oldValue = _Id; - SetId(oldValue, ref value); - if (oldValue != value) - { - _Id = value; - } - } - } - - /// - /// Required, ConcurrenyToken. - /// - [ConcurrencyCheck] - [Required] - public uint RowVersion { get; set; } + /// + [NotMapped] + public ICollection Companies => ChildCompanies; + /// public void OnSavingChanges() { RowVersion++; } - - /************************************************************************* - * Navigation properties - *************************************************************************/ - [ForeignKey("CompanyMetadata_CompanyMetadata_Id")] - public virtual ICollection CompanyMetadata { get; protected set; } - [ForeignKey("Company_Parent_Id")] - public virtual Company Parent { get; set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/CompanyMetadata.cs b/Jellyfin.Data/Entities/Libraries/CompanyMetadata.cs index f81beb0d58..60cc96a340 100644 --- a/Jellyfin.Data/Entities/Libraries/CompanyMetadata.cs +++ b/Jellyfin.Data/Entities/Libraries/CompanyMetadata.cs @@ -1,236 +1,74 @@ -#pragma warning disable CS1591 - using System; using System.ComponentModel.DataAnnotations; namespace Jellyfin.Data.Entities.Libraries { - public partial class CompanyMetadata : Metadata + /// + /// An entity holding metadata for a . + /// + public class CompanyMetadata : Metadata { - partial void Init(); - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. - /// - protected CompanyMetadata() - { - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static CompanyMetadata CreateCompanyMetadataUnsafe() - { - return new CompanyMetadata(); - } - - /// - /// Public constructor with required data. + /// Initializes a new instance of the class. /// /// The title or name of the object. /// ISO-639-3 3-character language codes. - /// The date the object was added. - /// The date the object was last modified. - /// - public CompanyMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Company _company0) + /// The company. + public CompanyMetadata(string title, string language, Company company) : base(title, language) { - if (string.IsNullOrEmpty(title)) - { - throw new ArgumentNullException(nameof(title)); - } - - this.Title = title; - - if (string.IsNullOrEmpty(language)) - { - throw new ArgumentNullException(nameof(language)); - } - - this.Language = language; - - if (_company0 == null) + if (company == null) { - throw new ArgumentNullException(nameof(_company0)); + throw new ArgumentNullException(nameof(company)); } - _company0.CompanyMetadata.Add(this); - - Init(); + company.CompanyMetadata.Add(this); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// The title or name of the object. - /// ISO-639-3 3-character language codes. - /// The date the object was added. - /// The date the object was last modified. - /// - public static CompanyMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, Company _company0) + protected CompanyMetadata() { - return new CompanyMetadata(title, language, dateadded, datemodified, _company0); } - /************************************************************************* - * Properties - *************************************************************************/ - /// - /// Backing field for Description. - /// - protected string _Description; - /// - /// When provided in a partial class, allows value of Description to be changed before setting. - /// - partial void SetDescription(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Description to be changed before returning. - /// - partial void GetDescription(ref string result); - - /// - /// Max length = 65535 + /// Gets or sets the description. /// + /// + /// Max length = 65535. + /// [MaxLength(65535)] [StringLength(65535)] - public string Description - { - get - { - string value = _Description; - GetDescription(ref value); - return _Description = value; - } - - set - { - string oldValue = _Description; - SetDescription(oldValue, ref value); - if (oldValue != value) - { - _Description = value; - } - } - } - - /// - /// Backing field for Headquarters. - /// - protected string _Headquarters; - /// - /// When provided in a partial class, allows value of Headquarters to be changed before setting. - /// - partial void SetHeadquarters(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Headquarters to be changed before returning. - /// - partial void GetHeadquarters(ref string result); + public string Description { get; set; } /// - /// Max length = 255 + /// Gets or sets the headquarters. /// + /// + /// Max length = 255. + /// [MaxLength(255)] [StringLength(255)] - public string Headquarters - { - get - { - string value = _Headquarters; - GetHeadquarters(ref value); - return _Headquarters = value; - } + public string Headquarters { get; set; } - set - { - string oldValue = _Headquarters; - SetHeadquarters(oldValue, ref value); - if (oldValue != value) - { - _Headquarters = value; - } - } - } - - /// - /// Backing field for Country. - /// - protected string _Country; - /// - /// When provided in a partial class, allows value of Country to be changed before setting. - /// - partial void SetCountry(string oldValue, ref string newValue); /// - /// When provided in a partial class, allows value of Country to be changed before returning. - /// - partial void GetCountry(ref string result); - - /// - /// Max length = 2 + /// Gets or sets the country code. /// + /// + /// Max length = 2. + /// [MaxLength(2)] [StringLength(2)] - public string Country - { - get - { - string value = _Country; - GetCountry(ref value); - return _Country = value; - } - - set - { - string oldValue = _Country; - SetCountry(oldValue, ref value); - if (oldValue != value) - { - _Country = value; - } - } - } + public string Country { get; set; } /// - /// Backing field for Homepage. - /// - protected string _Homepage; - /// - /// When provided in a partial class, allows value of Homepage to be changed before setting. - /// - partial void SetHomepage(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Homepage to be changed before returning. - /// - partial void GetHomepage(ref string result); - - /// - /// Max length = 1024 + /// Gets or sets the homepage. /// + /// + /// Max length = 1024. + /// [MaxLength(1024)] [StringLength(1024)] - public string Homepage - { - get - { - string value = _Homepage; - GetHomepage(ref value); - return _Homepage = value; - } - - set - { - string oldValue = _Homepage; - SetHomepage(oldValue, ref value); - if (oldValue != value) - { - _Homepage = value; - } - } - } - - /************************************************************************* - * Navigation properties - *************************************************************************/ + public string Homepage { get; set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/CustomItem.cs b/Jellyfin.Data/Entities/Libraries/CustomItem.cs index ffe06db249..6a4f0a5378 100644 --- a/Jellyfin.Data/Entities/Libraries/CustomItem.cs +++ b/Jellyfin.Data/Entities/Libraries/CustomItem.cs @@ -1,71 +1,28 @@ -#pragma warning disable CS1591 - -using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class CustomItem : LibraryItem + /// + /// An entity representing a custom item. + /// + public class CustomItem : LibraryItem, IHasReleases { - partial void Init(); - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. + /// Initializes a new instance of the class. /// - protected CustomItem() + public CustomItem() { CustomItemMetadata = new HashSet(); Releases = new HashSet(); - - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static CustomItem CreateCustomItemUnsafe() - { - return new CustomItem(); - } - - /// - /// Public constructor with required data. - /// - /// This is whats gets displayed in the Urls and API requests. This could also be a string. - /// The date the object was added. - public CustomItem(Guid urlid, DateTime dateadded) - { - this.UrlId = urlid; - - this.CustomItemMetadata = new HashSet(); - this.Releases = new HashSet(); - - Init(); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Gets or sets a collection containing the metadata for this item. /// - /// This is whats gets displayed in the Urls and API requests. This could also be a string. - /// The date the object was added. - public static CustomItem Create(Guid urlid, DateTime dateadded) - { - return new CustomItem(urlid, dateadded); - } - - /************************************************************************* - * Properties - *************************************************************************/ - - /************************************************************************* - * Navigation properties - *************************************************************************/ - [ForeignKey("CustomItemMetadata_CustomItemMetadata_Id")] public virtual ICollection CustomItemMetadata { get; protected set; } - [ForeignKey("Release_Releases_Id")] + /// public virtual ICollection Releases { get; protected set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/CustomItemMetadata.cs b/Jellyfin.Data/Entities/Libraries/CustomItemMetadata.cs index 8606302d7d..bc18355281 100644 --- a/Jellyfin.Data/Entities/Libraries/CustomItemMetadata.cs +++ b/Jellyfin.Data/Entities/Libraries/CustomItemMetadata.cs @@ -1,83 +1,36 @@ -#pragma warning disable CS1591 - using System; namespace Jellyfin.Data.Entities.Libraries { - public partial class CustomItemMetadata : Metadata + /// + /// An entity containing metadata for a custom item. + /// + public class CustomItemMetadata : Metadata { - partial void Init(); - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. - /// - protected CustomItemMetadata() - { - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static CustomItemMetadata CreateCustomItemMetadataUnsafe() - { - return new CustomItemMetadata(); - } - - /// - /// Public constructor with required data. + /// Initializes a new instance of the class. /// /// The title or name of the object. /// ISO-639-3 3-character language codes. - /// The date the object was added. - /// The date the object was last modified. - /// - public CustomItemMetadata(string title, string language, DateTime dateadded, DateTime datemodified, CustomItem _customitem0) + /// The item. + public CustomItemMetadata(string title, string language, CustomItem item) : base(title, language) { - if (string.IsNullOrEmpty(title)) - { - throw new ArgumentNullException(nameof(title)); - } - - this.Title = title; - - if (string.IsNullOrEmpty(language)) - { - throw new ArgumentNullException(nameof(language)); - } - - this.Language = language; - - if (_customitem0 == null) + if (item == null) { - throw new ArgumentNullException(nameof(_customitem0)); + throw new ArgumentNullException(nameof(item)); } - _customitem0.CustomItemMetadata.Add(this); - - Init(); + item.CustomItemMetadata.Add(this); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// The title or name of the object. - /// ISO-639-3 3-character language codes. - /// The date the object was added. - /// The date the object was last modified. - /// - public static CustomItemMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, CustomItem _customitem0) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected CustomItemMetadata() { - return new CustomItemMetadata(title, language, dateadded, datemodified, _customitem0); } - - /************************************************************************* - * Properties - *************************************************************************/ - - /************************************************************************* - * Navigation properties - *************************************************************************/ } } - diff --git a/Jellyfin.Data/Entities/Libraries/Episode.cs b/Jellyfin.Data/Entities/Libraries/Episode.cs index 3315b3e30b..430a11e3c8 100644 --- a/Jellyfin.Data/Entities/Libraries/Episode.cs +++ b/Jellyfin.Data/Entities/Libraries/Episode.cs @@ -1,118 +1,52 @@ -#pragma warning disable CS1591 - using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class Episode : LibraryItem + /// + /// An entity representing an episode. + /// + public class Episode : LibraryItem, IHasReleases { - partial void Init(); - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. + /// Initializes a new instance of the class. /// - protected Episode() + /// The season. + public Episode(Season season) { - // NOTE: This class has one-to-one associations with LibraryRoot, LibraryItem and CollectionItem. - // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other. + if (season == null) + { + throw new ArgumentNullException(nameof(season)); + } + + season.Episodes.Add(this); Releases = new HashSet(); EpisodeMetadata = new HashSet(); - - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static Episode CreateEpisodeUnsafe() - { - return new Episode(); } /// - /// Public constructor with required data. + /// Initializes a new instance of the class. /// - /// This is whats gets displayed in the Urls and API requests. This could also be a string. - /// The date the object was added. - /// - public Episode(Guid urlid, DateTime dateadded, Season _season0) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected Episode() { - // NOTE: This class has one-to-one associations with LibraryRoot, LibraryItem and CollectionItem. - // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other. - - this.UrlId = urlid; - - if (_season0 == null) - { - throw new ArgumentNullException(nameof(_season0)); - } - - _season0.Episodes.Add(this); - - this.Releases = new HashSet(); - this.EpisodeMetadata = new HashSet(); - - Init(); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Gets or sets the episode number. /// - /// This is whats gets displayed in the Urls and API requests. This could also be a string. - /// The date the object was added. - /// - public static Episode Create(Guid urlid, DateTime dateadded, Season _season0) - { - return new Episode(urlid, dateadded, _season0); - } + public int? EpisodeNumber { get; set; } - /************************************************************************* - * Properties - *************************************************************************/ + /// + public virtual ICollection Releases { get; protected set; } /// - /// Backing field for EpisodeNumber. + /// Gets or sets a collection containing the metadata for this episode. /// - protected int? _EpisodeNumber; - /// - /// When provided in a partial class, allows value of EpisodeNumber to be changed before setting. - /// - partial void SetEpisodeNumber(int? oldValue, ref int? newValue); - /// - /// When provided in a partial class, allows value of EpisodeNumber to be changed before returning. - /// - partial void GetEpisodeNumber(ref int? result); - - public int? EpisodeNumber - { - get - { - int? value = _EpisodeNumber; - GetEpisodeNumber(ref value); - return _EpisodeNumber = value; - } - - set - { - int? oldValue = _EpisodeNumber; - SetEpisodeNumber(oldValue, ref value); - if (oldValue != value) - { - _EpisodeNumber = value; - } - } - } - - /************************************************************************* - * Navigation properties - *************************************************************************/ - [ForeignKey("Release_Releases_Id")] - public virtual ICollection Releases { get; protected set; } - [ForeignKey("EpisodeMetadata_EpisodeMetadata_Id")] public virtual ICollection EpisodeMetadata { get; protected set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/EpisodeMetadata.cs b/Jellyfin.Data/Entities/Libraries/EpisodeMetadata.cs index f20ed3573f..348100cb4c 100644 --- a/Jellyfin.Data/Entities/Libraries/EpisodeMetadata.cs +++ b/Jellyfin.Data/Entities/Libraries/EpisodeMetadata.cs @@ -1,198 +1,67 @@ -#pragma warning disable CS1591 - using System; using System.ComponentModel.DataAnnotations; namespace Jellyfin.Data.Entities.Libraries { - public partial class EpisodeMetadata : Metadata + /// + /// An entity containing metadata for an . + /// + public class EpisodeMetadata : Metadata { - partial void Init(); - - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. - /// - protected EpisodeMetadata() - { - Init(); - } - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static EpisodeMetadata CreateEpisodeMetadataUnsafe() - { - return new EpisodeMetadata(); - } - - /// - /// Public constructor with required data. + /// Initializes a new instance of the class. /// /// The title or name of the object. /// ISO-639-3 3-character language codes. - /// The date the object was added. - /// The date the object was last modified. - /// - public EpisodeMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Episode _episode0) + /// The episode. + public EpisodeMetadata(string title, string language, Episode episode) : base(title, language) { - if (string.IsNullOrEmpty(title)) - { - throw new ArgumentNullException(nameof(title)); - } - - this.Title = title; - - if (string.IsNullOrEmpty(language)) + if (episode == null) { - throw new ArgumentNullException(nameof(language)); + throw new ArgumentNullException(nameof(episode)); } - this.Language = language; - - if (_episode0 == null) - { - throw new ArgumentNullException(nameof(_episode0)); - } - - _episode0.EpisodeMetadata.Add(this); - - Init(); + episode.EpisodeMetadata.Add(this); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// The title or name of the object. - /// ISO-639-3 3-character language codes. - /// The date the object was added. - /// The date the object was last modified. - /// - public static EpisodeMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, Episode _episode0) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected EpisodeMetadata() { - return new EpisodeMetadata(title, language, dateadded, datemodified, _episode0); } - /************************************************************************* - * Properties - *************************************************************************/ - - /// - /// Backing field for Outline. - /// - protected string _Outline; - /// - /// When provided in a partial class, allows value of Outline to be changed before setting. - /// - partial void SetOutline(string oldValue, ref string newValue); /// - /// When provided in a partial class, allows value of Outline to be changed before returning. - /// - partial void GetOutline(ref string result); - - /// - /// Max length = 1024 + /// Gets or sets the outline. /// + /// + /// Max length = 1024. + /// [MaxLength(1024)] [StringLength(1024)] - public string Outline - { - get - { - string value = _Outline; - GetOutline(ref value); - return _Outline = value; - } - - set - { - string oldValue = _Outline; - SetOutline(oldValue, ref value); - if (oldValue != value) - { - _Outline = value; - } - } - } - - /// - /// Backing field for Plot. - /// - protected string _Plot; - /// - /// When provided in a partial class, allows value of Plot to be changed before setting. - /// - partial void SetPlot(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Plot to be changed before returning. - /// - partial void GetPlot(ref string result); + public string Outline { get; set; } /// - /// Max length = 65535 + /// Gets or sets the plot. /// + /// + /// Max length = 65535. + /// [MaxLength(65535)] [StringLength(65535)] - public string Plot - { - get - { - string value = _Plot; - GetPlot(ref value); - return _Plot = value; - } - - set - { - string oldValue = _Plot; - SetPlot(oldValue, ref value); - if (oldValue != value) - { - _Plot = value; - } - } - } - - /// - /// Backing field for Tagline. - /// - protected string _Tagline; - /// - /// When provided in a partial class, allows value of Tagline to be changed before setting. - /// - partial void SetTagline(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Tagline to be changed before returning. - /// - partial void GetTagline(ref string result); + public string Plot { get; set; } /// - /// Max length = 1024 + /// Gets or sets the tagline. /// + /// + /// Max length = 1024. + /// [MaxLength(1024)] [StringLength(1024)] - public string Tagline - { - get - { - string value = _Tagline; - GetTagline(ref value); - return _Tagline = value; - } - - set - { - string oldValue = _Tagline; - SetTagline(oldValue, ref value); - if (oldValue != value) - { - _Tagline = value; - } - } - } - - /************************************************************************* - * Navigation properties - *************************************************************************/ + public string Tagline { get; set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/Genre.cs b/Jellyfin.Data/Entities/Libraries/Genre.cs index c0b391ac8c..aeedd7bfde 100644 --- a/Jellyfin.Data/Entities/Libraries/Genre.cs +++ b/Jellyfin.Data/Entities/Libraries/Genre.cs @@ -1,162 +1,75 @@ -#pragma warning disable CS1591 - using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class Genre + /// + /// An entity representing a genre. + /// + public class Genre : IHasConcurrencyToken { - partial void Init(); - - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. - /// - protected Genre() - { - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static Genre CreateGenreUnsafe() - { - return new Genre(); - } - /// - /// Public constructor with required data. + /// Initializes a new instance of the class. /// - /// - /// - public Genre(string name, Metadata _metadata0) + /// The name. + /// The metadata. + public Genre(string name, Metadata metadata) { if (string.IsNullOrEmpty(name)) { throw new ArgumentNullException(nameof(name)); } - this.Name = name; + Name = name; - if (_metadata0 == null) + if (metadata == null) { - throw new ArgumentNullException(nameof(_metadata0)); + throw new ArgumentNullException(nameof(metadata)); } - _metadata0.Genres.Add(this); - - Init(); + metadata.Genres.Add(this); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// - /// - public static Genre Create(string name, Metadata _metadata0) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected Genre() { - return new Genre(name, _metadata0); } - /************************************************************************* - * Properties - *************************************************************************/ - - /// - /// Backing field for Id. - /// - internal int _Id; /// - /// When provided in a partial class, allows value of Id to be changed before setting. + /// Gets or sets the id. /// - partial void SetId(int oldValue, ref int newValue); - /// - /// When provided in a partial class, allows value of Id to be changed before returning. - /// - partial void GetId(ref int result); - - /// + /// /// Identity, Indexed, Required. - /// - [Key] - [Required] + /// [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public int Id - { - get - { - int value = _Id; - GetId(ref value); - return _Id = value; - } - - protected set - { - int oldValue = _Id; - SetId(oldValue, ref value); - if (oldValue != value) - { - _Id = value; - } - } - } - - /// - /// Backing field for Name. - /// - internal string _Name; - /// - /// When provided in a partial class, allows value of Name to be changed before setting. - /// - partial void SetName(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Name to be changed before returning. - /// - partial void GetName(ref string result); + public int Id { get; protected set; } /// - /// Indexed, Required, Max length = 255 + /// Gets or sets the name. /// + /// + /// Indexed, Required, Max length = 255. + /// [Required] [MaxLength(255)] [StringLength(255)] - public string Name - { - get - { - string value = _Name; - GetName(ref value); - return _Name = value; - } + public string Name { get; set; } - set - { - string oldValue = _Name; - SetName(oldValue, ref value); - if (oldValue != value) - { - _Name = value; - } - } - } - - /// - /// Required, ConcurrenyToken. - /// + /// [ConcurrencyCheck] - [Required] - public uint RowVersion { get; set; } + public uint RowVersion { get; protected set; } + /// public void OnSavingChanges() { RowVersion++; } - - /************************************************************************* - * Navigation properties - *************************************************************************/ } } - diff --git a/Jellyfin.Data/Entities/Libraries/Library.cs b/Jellyfin.Data/Entities/Libraries/Library.cs index 9a97a3b00c..4f82a2e2a7 100644 --- a/Jellyfin.Data/Entities/Libraries/Library.cs +++ b/Jellyfin.Data/Entities/Libraries/Library.cs @@ -1,153 +1,76 @@ -#pragma warning disable CS1591 - using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class Library + /// + /// An entity representing a library. + /// + public class Library : IHasConcurrencyToken { - partial void Init(); - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. + /// Initializes a new instance of the class. /// - protected Library() - { - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static Library CreateLibraryUnsafe() - { - return new Library(); - } - - /// - /// Public constructor with required data. - /// - /// + /// The name of the library. public Library(string name) { - if (string.IsNullOrEmpty(name)) + if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentNullException(nameof(name)); } - this.Name = name; - - Init(); + Name = name; } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// - public static Library Create(string name) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected Library() { - return new Library(name); } - /************************************************************************* - * Properties - *************************************************************************/ - - /// - /// Backing field for Id. - /// - internal int _Id; - /// - /// When provided in a partial class, allows value of Id to be changed before setting. - /// - partial void SetId(int oldValue, ref int newValue); /// - /// When provided in a partial class, allows value of Id to be changed before returning. + /// Gets or sets the id. /// - partial void GetId(ref int result); - - /// + /// /// Identity, Indexed, Required. - /// - [Key] - [Required] + /// [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public int Id - { - get - { - int value = _Id; - GetId(ref value); - return _Id = value; - } + public int Id { get; protected set; } - protected set - { - int oldValue = _Id; - SetId(oldValue, ref value); - if (oldValue != value) - { - _Id = value; - } - } - } - - /// - /// Backing field for Name. - /// - protected string _Name; /// - /// When provided in a partial class, allows value of Name to be changed before setting. + /// Gets or sets the name. /// - partial void SetName(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Name to be changed before returning. - /// - partial void GetName(ref string result); + /// + /// Required, Max length = 128. + /// + [Required] + [MaxLength(128)] + [StringLength(128)] + public string Name { get; set; } /// - /// Required, Max length = 1024 + /// Gets or sets the root path of the library. /// + /// + /// Required. + /// [Required] - [MaxLength(1024)] - [StringLength(1024)] - public string Name - { - get - { - string value = _Name; - GetName(ref value); - return _Name = value; - } - - set - { - string oldValue = _Name; - SetName(oldValue, ref value); - if (oldValue != value) - { - _Name = value; - } - } - } + public string Path { get; set; } - /// - /// Required, ConcurrenyToken. - /// + /// [ConcurrencyCheck] - [Required] public uint RowVersion { get; set; } + /// public void OnSavingChanges() { RowVersion++; } - - /************************************************************************* - * Navigation properties - *************************************************************************/ } } - diff --git a/Jellyfin.Data/Entities/Libraries/LibraryItem.cs b/Jellyfin.Data/Entities/Libraries/LibraryItem.cs index b5f0323653..a9167aa7fd 100644 --- a/Jellyfin.Data/Entities/Libraries/LibraryItem.cs +++ b/Jellyfin.Data/Entities/Libraries/LibraryItem.cs @@ -1,175 +1,63 @@ -#pragma warning disable CS1591 - using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public abstract partial class LibraryItem + /// + /// An entity representing a library item. + /// + public abstract class LibraryItem : IHasConcurrencyToken { - partial void Init(); - /// - /// Default constructor. Protected due to being abstract. + /// Initializes a new instance of the class. /// - protected LibraryItem() + /// The library of this item. + protected LibraryItem(Library library) { - Init(); + DateAdded = DateTime.UtcNow; + Library = library; } /// - /// Public constructor with required data. + /// Initializes a new instance of the class. /// - /// This is whats gets displayed in the Urls and API requests. This could also be a string. - /// The date the object was added. - protected LibraryItem(Guid urlid, DateTime dateadded) + protected LibraryItem() { - this.UrlId = urlid; - - - Init(); } - /************************************************************************* - * Properties - *************************************************************************/ - /// - /// Backing field for Id. + /// Gets or sets the id. /// - internal int _Id; - /// - /// When provided in a partial class, allows value of Id to be changed before setting. - /// - partial void SetId(int oldValue, ref int newValue); - /// - /// When provided in a partial class, allows value of Id to be changed before returning. - /// - partial void GetId(ref int result); - - /// + /// /// Identity, Indexed, Required. - /// - [Key] - [Required] + /// [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public int Id - { - get - { - int value = _Id; - GetId(ref value); - return _Id = value; - } - - protected set - { - int oldValue = _Id; - SetId(oldValue, ref value); - if (oldValue != value) - { - _Id = value; - } - } - } - - /// - /// Backing field for UrlId. - /// - internal Guid _UrlId; - /// - /// When provided in a partial class, allows value of UrlId to be changed before setting. - /// - partial void SetUrlId(Guid oldValue, ref Guid newValue); - /// - /// When provided in a partial class, allows value of UrlId to be changed before returning. - /// - partial void GetUrlId(ref Guid result); + public int Id { get; protected set; } /// - /// Indexed, Required - /// This is whats gets displayed in the Urls and API requests. This could also be a string. + /// Gets or sets the date this library item was added. /// - [Required] - public Guid UrlId - { - get - { - Guid value = _UrlId; - GetUrlId(ref value); - return _UrlId = value; - } + public DateTime DateAdded { get; protected set; } - set - { - Guid oldValue = _UrlId; - SetUrlId(oldValue, ref value); - if (oldValue != value) - { - _UrlId = value; - } - } - } + /// + [ConcurrencyCheck] + public uint RowVersion { get; protected set; } /// - /// Backing field for DateAdded. + /// Gets or sets the library of this item. /// - protected DateTime _DateAdded; - /// - /// When provided in a partial class, allows value of DateAdded to be changed before setting. - /// - partial void SetDateAdded(DateTime oldValue, ref DateTime newValue); - /// - /// When provided in a partial class, allows value of DateAdded to be changed before returning. - /// - partial void GetDateAdded(ref DateTime result); - - /// + /// /// Required. - /// + /// [Required] - public DateTime DateAdded - { - get - { - DateTime value = _DateAdded; - GetDateAdded(ref value); - return _DateAdded = value; - } - - internal set - { - DateTime oldValue = _DateAdded; - SetDateAdded(oldValue, ref value); - if (oldValue != value) - { - _DateAdded = value; - } - } - } - - /// - /// Required, ConcurrenyToken. - /// - [ConcurrencyCheck] - [Required] - public uint RowVersion { get; set; } + public virtual Library Library { get; set; } + /// public void OnSavingChanges() { RowVersion++; } - - /************************************************************************* - * Navigation properties - *************************************************************************/ - - /// - /// Required. - /// - [ForeignKey("LibraryRoot_Id")] - public virtual LibraryRoot LibraryRoot { get; set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/LibraryRoot.cs b/Jellyfin.Data/Entities/Libraries/LibraryRoot.cs deleted file mode 100644 index bbd9044477..0000000000 --- a/Jellyfin.Data/Entities/Libraries/LibraryRoot.cs +++ /dev/null @@ -1,199 +0,0 @@ -#pragma warning disable CS1591 - -using System; -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; - -namespace Jellyfin.Data.Entities.Libraries -{ - public partial class LibraryRoot - { - partial void Init(); - - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. - /// - protected LibraryRoot() - { - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static LibraryRoot CreateLibraryRootUnsafe() - { - return new LibraryRoot(); - } - - /// - /// Public constructor with required data. - /// - /// Absolute Path. - public LibraryRoot(string path) - { - if (string.IsNullOrEmpty(path)) - { - throw new ArgumentNullException(nameof(path)); - } - - this.Path = path; - - Init(); - } - - /// - /// Static create function (for use in LINQ queries, etc.) - /// - /// Absolute Path. - public static LibraryRoot Create(string path) - { - return new LibraryRoot(path); - } - - /************************************************************************* - * Properties - *************************************************************************/ - - /// - /// Backing field for Id. - /// - internal int _Id; - /// - /// When provided in a partial class, allows value of Id to be changed before setting. - /// - partial void SetId(int oldValue, ref int newValue); - /// - /// When provided in a partial class, allows value of Id to be changed before returning. - /// - partial void GetId(ref int result); - - /// - /// Identity, Indexed, Required. - /// - [Key] - [Required] - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public int Id - { - get - { - int value = _Id; - GetId(ref value); - return _Id = value; - } - - protected set - { - int oldValue = _Id; - SetId(oldValue, ref value); - if (oldValue != value) - { - _Id = value; - } - } - } - - /// - /// Backing field for Path. - /// - protected string _Path; - /// - /// When provided in a partial class, allows value of Path to be changed before setting. - /// - partial void SetPath(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Path to be changed before returning. - /// - partial void GetPath(ref string result); - - /// - /// Required, Max length = 65535 - /// Absolute Path. - /// - [Required] - [MaxLength(65535)] - [StringLength(65535)] - public string Path - { - get - { - string value = _Path; - GetPath(ref value); - return _Path = value; - } - - set - { - string oldValue = _Path; - SetPath(oldValue, ref value); - if (oldValue != value) - { - _Path = value; - } - } - } - - /// - /// Backing field for NetworkPath. - /// - protected string _NetworkPath; - /// - /// When provided in a partial class, allows value of NetworkPath to be changed before setting. - /// - partial void SetNetworkPath(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of NetworkPath to be changed before returning. - /// - partial void GetNetworkPath(ref string result); - - /// - /// Max length = 65535 - /// Absolute network path, for example for transcoding sattelites. - /// - [MaxLength(65535)] - [StringLength(65535)] - public string NetworkPath - { - get - { - string value = _NetworkPath; - GetNetworkPath(ref value); - return _NetworkPath = value; - } - - set - { - string oldValue = _NetworkPath; - SetNetworkPath(oldValue, ref value); - if (oldValue != value) - { - _NetworkPath = value; - } - } - } - - /// - /// Required, ConcurrenyToken. - /// - [ConcurrencyCheck] - [Required] - public uint RowVersion { get; set; } - - public void OnSavingChanges() - { - RowVersion++; - } - - /************************************************************************* - * Navigation properties - *************************************************************************/ - - /// - /// Required. - /// - [ForeignKey("Library_Id")] - public virtual Library Library { get; set; } - } -} - diff --git a/Jellyfin.Data/Entities/Libraries/MediaFile.cs b/Jellyfin.Data/Entities/Libraries/MediaFile.cs index c9efdb143b..8bc649c98f 100644 --- a/Jellyfin.Data/Entities/Libraries/MediaFile.cs +++ b/Jellyfin.Data/Entities/Libraries/MediaFile.cs @@ -1,212 +1,94 @@ -#pragma warning disable CS1591 - using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Enums; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class MediaFile + /// + /// An entity representing a file on disk. + /// + public class MediaFile : IHasConcurrencyToken { - partial void Init(); - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. + /// Initializes a new instance of the class. /// - protected MediaFile() - { - MediaFileStreams = new HashSet(); - - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static MediaFile CreateMediaFileUnsafe() - { - return new MediaFile(); - } - - /// - /// Public constructor with required data. - /// - /// Relative to the LibraryRoot. - /// - /// - public MediaFile(string path, Enums.MediaFileKind kind, Release _release0) + /// The path relative to the LibraryRoot. + /// The file kind. + /// The release. + public MediaFile(string path, MediaFileKind kind, Release release) { if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException(nameof(path)); } - this.Path = path; - - this.Kind = kind; + Path = path; + Kind = kind; - if (_release0 == null) + if (release == null) { - throw new ArgumentNullException(nameof(_release0)); + throw new ArgumentNullException(nameof(release)); } - _release0.MediaFiles.Add(this); + release.MediaFiles.Add(this); - this.MediaFileStreams = new HashSet(); - - Init(); + MediaFileStreams = new HashSet(); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// Relative to the LibraryRoot. - /// - /// - public static MediaFile Create(string path, Enums.MediaFileKind kind, Release _release0) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected MediaFile() { - return new MediaFile(path, kind, _release0); } - /************************************************************************* - * Properties - *************************************************************************/ - - /// - /// Backing field for Id. - /// - internal int _Id; /// - /// When provided in a partial class, allows value of Id to be changed before setting. + /// Gets or sets the id. /// - partial void SetId(int oldValue, ref int newValue); - /// - /// When provided in a partial class, allows value of Id to be changed before returning. - /// - partial void GetId(ref int result); - - /// + /// /// Identity, Indexed, Required. - /// - [Key] - [Required] + /// [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public int Id - { - get - { - int value = _Id; - GetId(ref value); - return _Id = value; - } - - protected set - { - int oldValue = _Id; - SetId(oldValue, ref value); - if (oldValue != value) - { - _Id = value; - } - } - } + public int Id { get; protected set; } /// - /// Backing field for Path. - /// - protected string _Path; - /// - /// When provided in a partial class, allows value of Path to be changed before setting. - /// - partial void SetPath(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Path to be changed before returning. - /// - partial void GetPath(ref string result); - - /// - /// Required, Max length = 65535 - /// Relative to the LibraryRoot. + /// Gets or sets the path relative to the library root. /// + /// + /// Required, Max length = 65535. + /// [Required] [MaxLength(65535)] [StringLength(65535)] - public string Path - { - get - { - string value = _Path; - GetPath(ref value); - return _Path = value; - } + public string Path { get; set; } - set - { - string oldValue = _Path; - SetPath(oldValue, ref value); - if (oldValue != value) - { - _Path = value; - } - } - } - - /// - /// Backing field for Kind. - /// - protected Enums.MediaFileKind _Kind; /// - /// When provided in a partial class, allows value of Kind to be changed before setting. + /// Gets or sets the kind of media file. /// - partial void SetKind(Enums.MediaFileKind oldValue, ref Enums.MediaFileKind newValue); - /// - /// When provided in a partial class, allows value of Kind to be changed before returning. - /// - partial void GetKind(ref Enums.MediaFileKind result); - - /// + /// /// Required. - /// - [Required] - public Enums.MediaFileKind Kind - { - get - { - Enums.MediaFileKind value = _Kind; - GetKind(ref value); - return _Kind = value; - } + /// + public MediaFileKind Kind { get; set; } - set - { - Enums.MediaFileKind oldValue = _Kind; - SetKind(oldValue, ref value); - if (oldValue != value) - { - _Kind = value; - } - } - } + /// + [ConcurrencyCheck] + public uint RowVersion { get; set; } /// - /// Required, ConcurrenyToken. + /// Gets or sets a collection containing the streams in this file. /// - [ConcurrencyCheck] - [Required] - public uint RowVersion { get; set; } + public virtual ICollection MediaFileStreams { get; protected set; } + /// public void OnSavingChanges() { RowVersion++; } - - /************************************************************************* - * Navigation properties - *************************************************************************/ - - [ForeignKey("MediaFileStream_MediaFileStreams_Id")] - public virtual ICollection MediaFileStreams { get; protected set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/MediaFileStream.cs b/Jellyfin.Data/Entities/Libraries/MediaFileStream.cs index f1f26ecbb9..5b03e260e2 100644 --- a/Jellyfin.Data/Entities/Libraries/MediaFileStream.cs +++ b/Jellyfin.Data/Entities/Libraries/MediaFileStream.cs @@ -1,155 +1,67 @@ -#pragma warning disable CS1591 - using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class MediaFileStream + /// + /// An entity representing a stream in a media file. + /// + public class MediaFileStream : IHasConcurrencyToken { - partial void Init(); - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. + /// Initializes a new instance of the class. /// - protected MediaFileStream() + /// The number of this stream. + /// The media file. + public MediaFileStream(int streamNumber, MediaFile mediaFile) { - Init(); - } + StreamNumber = streamNumber; - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static MediaFileStream CreateMediaFileStreamUnsafe() - { - return new MediaFileStream(); - } - - /// - /// Public constructor with required data. - /// - /// - /// - public MediaFileStream(int streamnumber, MediaFile _mediafile0) - { - this.StreamNumber = streamnumber; - - if (_mediafile0 == null) + if (mediaFile == null) { - throw new ArgumentNullException(nameof(_mediafile0)); + throw new ArgumentNullException(nameof(mediaFile)); } - _mediafile0.MediaFileStreams.Add(this); - - Init(); + mediaFile.MediaFileStreams.Add(this); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// - /// - public static MediaFileStream Create(int streamnumber, MediaFile _mediafile0) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected MediaFileStream() { - return new MediaFileStream(streamnumber, _mediafile0); } - /************************************************************************* - * Properties - *************************************************************************/ - - /// - /// Backing field for Id. - /// - internal int _Id; - /// - /// When provided in a partial class, allows value of Id to be changed before setting. - /// - partial void SetId(int oldValue, ref int newValue); /// - /// When provided in a partial class, allows value of Id to be changed before returning. + /// Gets or sets the id. /// - partial void GetId(ref int result); - - /// + /// /// Identity, Indexed, Required. - /// - [Key] - [Required] + /// [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public int Id - { - get - { - int value = _Id; - GetId(ref value); - return _Id = value; - } - - protected set - { - int oldValue = _Id; - SetId(oldValue, ref value); - if (oldValue != value) - { - _Id = value; - } - } - } + public int Id { get; protected set; } /// - /// Backing field for StreamNumber. + /// Gets or sets the stream number. /// - protected int _StreamNumber; - /// - /// When provided in a partial class, allows value of StreamNumber to be changed before setting. - /// - partial void SetStreamNumber(int oldValue, ref int newValue); - /// - /// When provided in a partial class, allows value of StreamNumber to be changed before returning. - /// - partial void GetStreamNumber(ref int result); - - /// + /// /// Required. - /// - [Required] - public int StreamNumber - { - get - { - int value = _StreamNumber; - GetStreamNumber(ref value); - return _StreamNumber = value; - } - - set - { - int oldValue = _StreamNumber; - SetStreamNumber(oldValue, ref value); - if (oldValue != value) - { - _StreamNumber = value; - } - } - } + /// + public int StreamNumber { get; set; } - /// - /// Required, ConcurrenyToken. - /// + /// [ConcurrencyCheck] - [Required] public uint RowVersion { get; set; } + /// public void OnSavingChanges() { RowVersion++; } - - /************************************************************************* - * Navigation properties - *************************************************************************/ } } - diff --git a/Jellyfin.Data/Entities/Libraries/Metadata.cs b/Jellyfin.Data/Entities/Libraries/Metadata.cs index 449e807dec..877bb5fbdc 100644 --- a/Jellyfin.Data/Entities/Libraries/Metadata.cs +++ b/Jellyfin.Data/Entities/Libraries/Metadata.cs @@ -1,399 +1,165 @@ -#pragma warning disable CS1591 - using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public abstract partial class Metadata + /// + /// An abstract class that holds metadata. + /// + public abstract class Metadata : IHasArtwork, IHasConcurrencyToken { - partial void Init(); - - /// - /// Default constructor. Protected due to being abstract. - /// - protected Metadata() - { - PersonRoles = new HashSet(); - Genres = new HashSet(); - Artwork = new HashSet(); - Ratings = new HashSet(); - Sources = new HashSet(); - - Init(); - } - /// - /// Public constructor with required data. + /// Initializes a new instance of the class. /// /// The title or name of the object. /// ISO-639-3 3-character language codes. - /// The date the object was added. - /// The date the object was last modified. - protected Metadata(string title, string language, DateTime dateadded, DateTime datemodified) + protected Metadata(string title, string language) { if (string.IsNullOrEmpty(title)) { throw new ArgumentNullException(nameof(title)); } - this.Title = title; - if (string.IsNullOrEmpty(language)) { throw new ArgumentNullException(nameof(language)); } - this.Language = language; - - this.PersonRoles = new HashSet(); - this.Genres = new HashSet(); - this.Artwork = new HashSet(); - this.Ratings = new HashSet(); - this.Sources = new HashSet(); + Title = title; + Language = language; + DateAdded = DateTime.UtcNow; + DateModified = DateAdded; - Init(); + PersonRoles = new HashSet(); + Genres = new HashSet(); + Artwork = new HashSet(); + Ratings = new HashSet(); + Sources = new HashSet(); } - /************************************************************************* - * Properties - *************************************************************************/ - - /// - /// Backing field for Id. - /// - internal int _Id; /// - /// When provided in a partial class, allows value of Id to be changed before setting. + /// Initializes a new instance of the class. /// - partial void SetId(int oldValue, ref int newValue); - /// - /// When provided in a partial class, allows value of Id to be changed before returning. - /// - partial void GetId(ref int result); - - /// - /// Identity, Indexed, Required. - /// - [Key] - [Required] - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public int Id + /// + /// Default constructor. Protected due to being abstract. + /// + protected Metadata() { - get - { - int value = _Id; - GetId(ref value); - return _Id = value; - } - - protected set - { - int oldValue = _Id; - SetId(oldValue, ref value); - if (oldValue != value) - { - _Id = value; - } - } } /// - /// Backing field for Title. - /// - protected string _Title; - /// - /// When provided in a partial class, allows value of Title to be changed before setting. - /// - partial void SetTitle(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Title to be changed before returning. + /// Gets or sets the id. /// - partial void GetTitle(ref string result); + /// + /// Identity, Indexed, Required. + /// + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int Id { get; protected set; } /// - /// Required, Max length = 1024 - /// The title or name of the object. + /// Gets or sets the title. /// + /// + /// Required, Max length = 1024. + /// [Required] [MaxLength(1024)] [StringLength(1024)] - public string Title - { - get - { - string value = _Title; - GetTitle(ref value); - return _Title = value; - } + public string Title { get; set; } - set - { - string oldValue = _Title; - SetTitle(oldValue, ref value); - if (oldValue != value) - { - _Title = value; - } - } - } - - /// - /// Backing field for OriginalTitle. - /// - protected string _OriginalTitle; - /// - /// When provided in a partial class, allows value of OriginalTitle to be changed before setting. - /// - partial void SetOriginalTitle(string oldValue, ref string newValue); /// - /// When provided in a partial class, allows value of OriginalTitle to be changed before returning. - /// - partial void GetOriginalTitle(ref string result); - - /// - /// Max length = 1024 + /// Gets or sets the original title. /// + /// + /// Max length = 1024. + /// [MaxLength(1024)] [StringLength(1024)] - public string OriginalTitle - { - get - { - string value = _OriginalTitle; - GetOriginalTitle(ref value); - return _OriginalTitle = value; - } - - set - { - string oldValue = _OriginalTitle; - SetOriginalTitle(oldValue, ref value); - if (oldValue != value) - { - _OriginalTitle = value; - } - } - } + public string OriginalTitle { get; set; } /// - /// Backing field for SortTitle. - /// - protected string _SortTitle; - /// - /// When provided in a partial class, allows value of SortTitle to be changed before setting. - /// - partial void SetSortTitle(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of SortTitle to be changed before returning. - /// - partial void GetSortTitle(ref string result); - - /// - /// Max length = 1024 + /// Gets or sets the sort title. /// + /// + /// Max length = 1024. + /// [MaxLength(1024)] [StringLength(1024)] - public string SortTitle - { - get - { - string value = _SortTitle; - GetSortTitle(ref value); - return _SortTitle = value; - } - - set - { - string oldValue = _SortTitle; - SetSortTitle(oldValue, ref value); - if (oldValue != value) - { - _SortTitle = value; - } - } - } + public string SortTitle { get; set; } /// - /// Backing field for Language. - /// - protected string _Language; - /// - /// When provided in a partial class, allows value of Language to be changed before setting. + /// Gets or sets the language. /// - partial void SetLanguage(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Language to be changed before returning. - /// - partial void GetLanguage(ref string result); - - /// - /// Required, Min length = 3, Max length = 3 + /// + /// Required, Min length = 3, Max length = 3. /// ISO-639-3 3-character language codes. - /// + /// [Required] [MinLength(3)] [MaxLength(3)] [StringLength(3)] - public string Language - { - get - { - string value = _Language; - GetLanguage(ref value); - return _Language = value; - } - - set - { - string oldValue = _Language; - SetLanguage(oldValue, ref value); - if (oldValue != value) - { - _Language = value; - } - } - } + public string Language { get; set; } /// - /// Backing field for ReleaseDate. + /// Gets or sets the release date. /// - protected DateTimeOffset? _ReleaseDate; - /// - /// When provided in a partial class, allows value of ReleaseDate to be changed before setting. - /// - partial void SetReleaseDate(DateTimeOffset? oldValue, ref DateTimeOffset? newValue); - /// - /// When provided in a partial class, allows value of ReleaseDate to be changed before returning. - /// - partial void GetReleaseDate(ref DateTimeOffset? result); - - public DateTimeOffset? ReleaseDate - { - get - { - DateTimeOffset? value = _ReleaseDate; - GetReleaseDate(ref value); - return _ReleaseDate = value; - } - - set - { - DateTimeOffset? oldValue = _ReleaseDate; - SetReleaseDate(oldValue, ref value); - if (oldValue != value) - { - _ReleaseDate = value; - } - } - } + public DateTimeOffset? ReleaseDate { get; set; } /// - /// Backing field for DateAdded. + /// Gets or sets the date added. /// - protected DateTime _DateAdded; - /// - /// When provided in a partial class, allows value of DateAdded to be changed before setting. - /// - partial void SetDateAdded(DateTime oldValue, ref DateTime newValue); - /// - /// When provided in a partial class, allows value of DateAdded to be changed before returning. - /// - partial void GetDateAdded(ref DateTime result); + /// + /// Required. + /// + public DateTime DateAdded { get; protected set; } /// - /// Required. + /// Gets or sets the date modified. /// - [Required] - public DateTime DateAdded - { - get - { - DateTime value = _DateAdded; - GetDateAdded(ref value); - return _DateAdded = value; - } - - internal set - { - DateTime oldValue = _DateAdded; - SetDateAdded(oldValue, ref value); - if (oldValue != value) - { - _DateAdded = value; - } - } - } + /// + /// Required. + /// + public DateTime DateModified { get; set; } /// - /// Backing field for DateModified. + /// Gets or sets the row version. /// - protected DateTime _DateModified; + /// + /// Required, ConcurrencyToken. + /// + [ConcurrencyCheck] + public uint RowVersion { get; set; } + /// - /// When provided in a partial class, allows value of DateModified to be changed before setting. + /// Gets or sets a collection containing the person roles for this item. /// - partial void SetDateModified(DateTime oldValue, ref DateTime newValue); + public virtual ICollection PersonRoles { get; protected set; } + /// - /// When provided in a partial class, allows value of DateModified to be changed before returning. + /// Gets or sets a collection containing the generes for this item. /// - partial void GetDateModified(ref DateTime result); + public virtual ICollection Genres { get; protected set; } + + /// + public virtual ICollection Artwork { get; protected set; } /// - /// Required. + /// Gets or sets a collection containing the ratings for this item. /// - [Required] - public DateTime DateModified - { - get - { - DateTime value = _DateModified; - GetDateModified(ref value); - return _DateModified = value; - } - - internal set - { - DateTime oldValue = _DateModified; - SetDateModified(oldValue, ref value); - if (oldValue != value) - { - _DateModified = value; - } - } - } + public virtual ICollection Ratings { get; protected set; } /// - /// Required, ConcurrenyToken. + /// Gets or sets a collection containing the metadata sources for this item. /// - [ConcurrencyCheck] - [Required] - public uint RowVersion { get; set; } + public virtual ICollection Sources { get; protected set; } + /// public void OnSavingChanges() { RowVersion++; } - - /************************************************************************* - * Navigation properties - *************************************************************************/ - - [ForeignKey("PersonRole_PersonRoles_Id")] - public virtual ICollection PersonRoles { get; protected set; } - - [ForeignKey("PersonRole_PersonRoles_Id")] - public virtual ICollection Genres { get; protected set; } - - [ForeignKey("PersonRole_PersonRoles_Id")] - public virtual ICollection Artwork { get; protected set; } - - [ForeignKey("PersonRole_PersonRoles_Id")] - public virtual ICollection Ratings { get; protected set; } - - [ForeignKey("PersonRole_PersonRoles_Id")] - public virtual ICollection Sources { get; protected set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/MetadataProvider.cs b/Jellyfin.Data/Entities/Libraries/MetadataProvider.cs index d5462113b0..a18a612bcd 100644 --- a/Jellyfin.Data/Entities/Libraries/MetadataProvider.cs +++ b/Jellyfin.Data/Entities/Libraries/MetadataProvider.cs @@ -1,35 +1,19 @@ -#pragma warning disable CS1591 - using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class MetadataProvider + /// + /// An entity representing a metadata provider. + /// + public class MetadataProvider : IHasConcurrencyToken { - partial void Init(); - - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. - /// - protected MetadataProvider() - { - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static MetadataProvider CreateMetadataProviderUnsafe() - { - return new MetadataProvider(); - } - /// - /// Public constructor with required data. + /// Initializes a new instance of the class. /// - /// + /// The name of the metadata provider. public MetadataProvider(string name) { if (string.IsNullOrEmpty(name)) @@ -37,117 +21,47 @@ namespace Jellyfin.Data.Entities.Libraries throw new ArgumentNullException(nameof(name)); } - this.Name = name; - - Init(); + Name = name; } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// - public static MetadataProvider Create(string name) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected MetadataProvider() { - return new MetadataProvider(name); } - /************************************************************************* - * Properties - *************************************************************************/ - - /// - /// Backing field for Id. - /// - internal int _Id; /// - /// When provided in a partial class, allows value of Id to be changed before setting. + /// Gets or sets the id. /// - partial void SetId(int oldValue, ref int newValue); - /// - /// When provided in a partial class, allows value of Id to be changed before returning. - /// - partial void GetId(ref int result); - - /// + /// /// Identity, Indexed, Required. - /// - [Key] - [Required] + /// [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public int Id - { - get - { - int value = _Id; - GetId(ref value); - return _Id = value; - } - - protected set - { - int oldValue = _Id; - SetId(oldValue, ref value); - if (oldValue != value) - { - _Id = value; - } - } - } - - /// - /// Backing field for Name. - /// - protected string _Name; - /// - /// When provided in a partial class, allows value of Name to be changed before setting. - /// - partial void SetName(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Name to be changed before returning. - /// - partial void GetName(ref string result); + public int Id { get; protected set; } /// - /// Required, Max length = 1024 + /// Gets or sets the name. /// + /// + /// Required, Max length = 1024. + /// [Required] [MaxLength(1024)] [StringLength(1024)] - public string Name - { - get - { - string value = _Name; - GetName(ref value); - return _Name = value; - } + public string Name { get; set; } - set - { - string oldValue = _Name; - SetName(oldValue, ref value); - if (oldValue != value) - { - _Name = value; - } - } - } - - /// - /// Required, ConcurrenyToken. - /// + /// [ConcurrencyCheck] - [Required] public uint RowVersion { get; set; } + /// public void OnSavingChanges() { RowVersion++; } - - /************************************************************************* - * Navigation properties - *************************************************************************/ } } - diff --git a/Jellyfin.Data/Entities/Libraries/MetadataProviderId.cs b/Jellyfin.Data/Entities/Libraries/MetadataProviderId.cs index fed9d4f0bf..6e6de598e8 100644 --- a/Jellyfin.Data/Entities/Libraries/MetadataProviderId.cs +++ b/Jellyfin.Data/Entities/Libraries/MetadataProviderId.cs @@ -1,201 +1,83 @@ -#pragma warning disable CS1591 - using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class MetadataProviderId + /// + /// An entity representing a unique identifier for a metadata provider. + /// + public class MetadataProviderId : IHasConcurrencyToken { - partial void Init(); - - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. - /// - protected MetadataProviderId() - { - // NOTE: This class has one-to-one associations with MetadataProviderId. - // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other. - - Init(); - } - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. + /// Initializes a new instance of the class. /// - public static MetadataProviderId CreateMetadataProviderIdUnsafe() + /// The provider id. + /// The metadata entity. + public MetadataProviderId(string providerId, Metadata metadata) { - return new MetadataProviderId(); - } - - /// - /// Public constructor with required data. - /// - /// - /// - /// - /// - /// - public MetadataProviderId(string providerid, Metadata _metadata0, Person _person1, PersonRole _personrole2, RatingSource _ratingsource3) - { - // NOTE: This class has one-to-one associations with MetadataProviderId. - // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other. - - if (string.IsNullOrEmpty(providerid)) + if (string.IsNullOrEmpty(providerId)) { - throw new ArgumentNullException(nameof(providerid)); + throw new ArgumentNullException(nameof(providerId)); } - this.ProviderId = providerid; + ProviderId = providerId; - if (_metadata0 == null) + if (metadata == null) { - throw new ArgumentNullException(nameof(_metadata0)); + throw new ArgumentNullException(nameof(metadata)); } - _metadata0.Sources.Add(this); - - if (_person1 == null) - { - throw new ArgumentNullException(nameof(_person1)); - } - - _person1.Sources.Add(this); - - if (_personrole2 == null) - { - throw new ArgumentNullException(nameof(_personrole2)); - } - - _personrole2.Sources.Add(this); - - if (_ratingsource3 == null) - { - throw new ArgumentNullException(nameof(_ratingsource3)); - } - - _ratingsource3.Source = this; - - Init(); + metadata.Sources.Add(this); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// - /// - /// - /// - /// - public static MetadataProviderId Create(string providerid, Metadata _metadata0, Person _person1, PersonRole _personrole2, RatingSource _ratingsource3) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected MetadataProviderId() { - return new MetadataProviderId(providerid, _metadata0, _person1, _personrole2, _ratingsource3); } - /************************************************************************* - * Properties - *************************************************************************/ - /// - /// Backing field for Id. + /// Gets or sets the id. /// - internal int _Id; - /// - /// When provided in a partial class, allows value of Id to be changed before setting. - /// - partial void SetId(int oldValue, ref int newValue); - /// - /// When provided in a partial class, allows value of Id to be changed before returning. - /// - partial void GetId(ref int result); - - /// + /// /// Identity, Indexed, Required. - /// - [Key] - [Required] + /// [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public int Id - { - get - { - int value = _Id; - GetId(ref value); - return _Id = value; - } - - protected set - { - int oldValue = _Id; - SetId(oldValue, ref value); - if (oldValue != value) - { - _Id = value; - } - } - } + public int Id { get; protected set; } /// - /// Backing field for ProviderId. - /// - protected string _ProviderId; - /// - /// When provided in a partial class, allows value of ProviderId to be changed before setting. - /// - partial void SetProviderId(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of ProviderId to be changed before returning. - /// - partial void GetProviderId(ref string result); - - /// - /// Required, Max length = 255 + /// Gets or sets the provider id. /// + /// + /// Required, Max length = 255. + /// [Required] [MaxLength(255)] [StringLength(255)] - public string ProviderId - { - get - { - string value = _ProviderId; - GetProviderId(ref value); - return _ProviderId = value; - } + public string ProviderId { get; set; } - set - { - string oldValue = _ProviderId; - SetProviderId(oldValue, ref value); - if (oldValue != value) - { - _ProviderId = value; - } - } - } + /// + [ConcurrencyCheck] + public uint RowVersion { get; set; } /// - /// Required, ConcurrenyToken. + /// Gets or sets the metadata provider. /// - [ConcurrencyCheck] - [Required] - public uint RowVersion { get; set; } + /// + /// Required. + /// + public virtual MetadataProvider MetadataProvider { get; set; } + /// public void OnSavingChanges() { RowVersion++; } - - /************************************************************************* - * Navigation properties - *************************************************************************/ - - /// - /// Required. - /// - [ForeignKey("MetadataProvider_Id")] - public virtual MetadataProvider MetadataProvider { get; set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/Movie.cs b/Jellyfin.Data/Entities/Libraries/Movie.cs index e7d27b5519..0a8cc83dda 100644 --- a/Jellyfin.Data/Entities/Libraries/Movie.cs +++ b/Jellyfin.Data/Entities/Libraries/Movie.cs @@ -1,72 +1,28 @@ -#pragma warning disable CS1591 - -using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class Movie : LibraryItem + /// + /// An entity representing a movie. + /// + public class Movie : LibraryItem, IHasReleases { - partial void Init(); - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. + /// Initializes a new instance of the class. /// - protected Movie() + public Movie() { Releases = new HashSet(); MovieMetadata = new HashSet(); - - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static Movie CreateMovieUnsafe() - { - return new Movie(); } - /// - /// Public constructor with required data. - /// - /// This is whats gets displayed in the Urls and API requests. This could also be a string. - /// The date the object was added. - public Movie(Guid urlid, DateTime dateadded) - { - this.UrlId = urlid; - - this.Releases = new HashSet(); - this.MovieMetadata = new HashSet(); - - Init(); - } + /// + public virtual ICollection Releases { get; protected set; } /// - /// Static create function (for use in LINQ queries, etc.) + /// Gets or sets a collection containing the metadata for this movie. /// - /// This is whats gets displayed in the Urls and API requests. This could also be a string. - /// The date the object was added. - public static Movie Create(Guid urlid, DateTime dateadded) - { - return new Movie(urlid, dateadded); - } - - /************************************************************************* - * Properties - *************************************************************************/ - - /************************************************************************* - * Navigation properties - *************************************************************************/ - - [ForeignKey("Release_Releases_Id")] - public virtual ICollection Releases { get; protected set; } - - [ForeignKey("MovieMetadata_MovieMetadata_Id")] public virtual ICollection MovieMetadata { get; protected set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/MovieMetadata.cs b/Jellyfin.Data/Entities/Libraries/MovieMetadata.cs index f65da11d20..31102bf130 100644 --- a/Jellyfin.Data/Entities/Libraries/MovieMetadata.cs +++ b/Jellyfin.Data/Entities/Libraries/MovieMetadata.cs @@ -1,244 +1,85 @@ -#pragma warning disable CS1591 - -using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class MovieMetadata : Metadata + /// + /// An entity holding the metadata for a movie. + /// + public class MovieMetadata : Metadata, IHasCompanies { - partial void Init(); - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. + /// Initializes a new instance of the class. /// - protected MovieMetadata() - { - Studios = new HashSet(); - - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static MovieMetadata CreateMovieMetadataUnsafe() - { - return new MovieMetadata(); - } - - /// - /// Public constructor with required data. - /// - /// The title or name of the object. + /// The title or name of the movie. /// ISO-639-3 3-character language codes. - /// The date the object was added. - /// The date the object was last modified. - /// - public MovieMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Movie _movie0) + /// The movie. + public MovieMetadata(string title, string language, Movie movie) : base(title, language) { - if (string.IsNullOrEmpty(title)) - { - throw new ArgumentNullException(nameof(title)); - } - - this.Title = title; - - if (string.IsNullOrEmpty(language)) - { - throw new ArgumentNullException(nameof(language)); - } - - this.Language = language; - - if (_movie0 == null) - { - throw new ArgumentNullException(nameof(_movie0)); - } - - _movie0.MovieMetadata.Add(this); - - this.Studios = new HashSet(); + Studios = new HashSet(); - Init(); + movie.MovieMetadata.Add(this); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// The title or name of the object. - /// ISO-639-3 3-character language codes. - /// The date the object was added. - /// The date the object was last modified. - /// - public static MovieMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, Movie _movie0) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected MovieMetadata() { - return new MovieMetadata(title, language, dateadded, datemodified, _movie0); } - /************************************************************************* - * Properties - *************************************************************************/ - - /// - /// Backing field for Outline. - /// - protected string _Outline; /// - /// When provided in a partial class, allows value of Outline to be changed before setting. - /// - partial void SetOutline(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Outline to be changed before returning. - /// - partial void GetOutline(ref string result); - - /// - /// Max length = 1024 + /// Gets or sets the outline. /// + /// + /// Max length = 1024. + /// [MaxLength(1024)] [StringLength(1024)] - public string Outline - { - get - { - string value = _Outline; - GetOutline(ref value); - return _Outline = value; - } - - set - { - string oldValue = _Outline; - SetOutline(oldValue, ref value); - if (oldValue != value) - { - _Outline = value; - } - } - } + public string Outline { get; set; } /// - /// Backing field for Plot. - /// - protected string _Plot; - /// - /// When provided in a partial class, allows value of Plot to be changed before setting. - /// - partial void SetPlot(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Plot to be changed before returning. - /// - partial void GetPlot(ref string result); - - /// - /// Max length = 65535 - /// - [MaxLength(65535)] - [StringLength(65535)] - public string Plot - { - get - { - string value = _Plot; - GetPlot(ref value); - return _Plot = value; - } - - set - { - string oldValue = _Plot; - SetPlot(oldValue, ref value); - if (oldValue != value) - { - _Plot = value; - } - } - } - - /// - /// Backing field for Tagline. - /// - protected string _Tagline; - /// - /// When provided in a partial class, allows value of Tagline to be changed before setting. - /// - partial void SetTagline(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Tagline to be changed before returning. - /// - partial void GetTagline(ref string result); - - /// - /// Max length = 1024 + /// Gets or sets the tagline. /// + /// + /// Max length = 1024. + /// [MaxLength(1024)] [StringLength(1024)] - public string Tagline - { - get - { - string value = _Tagline; - GetTagline(ref value); - return _Tagline = value; - } - - set - { - string oldValue = _Tagline; - SetTagline(oldValue, ref value); - if (oldValue != value) - { - _Tagline = value; - } - } - } + public string Tagline { get; set; } /// - /// Backing field for Country. - /// - protected string _Country; - /// - /// When provided in a partial class, allows value of Country to be changed before setting. - /// - partial void SetCountry(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Country to be changed before returning. + /// Gets or sets the plot. /// - partial void GetCountry(ref string result); + /// + /// Max length = 65535. + /// + [MaxLength(65535)] + [StringLength(65535)] + public string Plot { get; set; } /// - /// Max length = 2 + /// Gets or sets the country code. /// + /// + /// Max length = 2. + /// [MaxLength(2)] [StringLength(2)] - public string Country - { - get - { - string value = _Country; - GetCountry(ref value); - return _Country = value; - } - - set - { - string oldValue = _Country; - SetCountry(oldValue, ref value); - if (oldValue != value) - { - _Country = value; - } - } - } + public string Country { get; set; } - /************************************************************************* - * Navigation properties - *************************************************************************/ - [ForeignKey("Company_Studios_Id")] + /// + /// Gets or sets the studios that produced this movie. + /// public virtual ICollection Studios { get; protected set; } + + /// + [NotMapped] + public ICollection Companies => Studios; } } - diff --git a/Jellyfin.Data/Entities/Libraries/MusicAlbum.cs b/Jellyfin.Data/Entities/Libraries/MusicAlbum.cs index 52776b12e6..2ed1f78c56 100644 --- a/Jellyfin.Data/Entities/Libraries/MusicAlbum.cs +++ b/Jellyfin.Data/Entities/Libraries/MusicAlbum.cs @@ -1,71 +1,29 @@ -#pragma warning disable CS1591 - -using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; namespace Jellyfin.Data.Entities.Libraries { - public partial class MusicAlbum : LibraryItem + /// + /// An entity representing a music album. + /// + public class MusicAlbum : LibraryItem { - partial void Init(); - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. + /// Initializes a new instance of the class. /// - protected MusicAlbum() + public MusicAlbum() { MusicAlbumMetadata = new HashSet(); Tracks = new HashSet(); - - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static MusicAlbum CreateMusicAlbumUnsafe() - { - return new MusicAlbum(); } /// - /// Public constructor with required data. + /// Gets or sets a collection containing the album metadata. /// - /// This is whats gets displayed in the Urls and API requests. This could also be a string. - /// The date the object was added. - public MusicAlbum(Guid urlid, DateTime dateadded) - { - this.UrlId = urlid; - - this.MusicAlbumMetadata = new HashSet(); - this.Tracks = new HashSet(); - - Init(); - } + public virtual ICollection MusicAlbumMetadata { get; protected set; } /// - /// Static create function (for use in LINQ queries, etc.) + /// Gets or sets a collection containing the tracks. /// - /// This is whats gets displayed in the Urls and API requests. This could also be a string. - /// The date the object was added. - public static MusicAlbum Create(Guid urlid, DateTime dateadded) - { - return new MusicAlbum(urlid, dateadded); - } - - /************************************************************************* - * Properties - *************************************************************************/ - - /************************************************************************* - * Navigation properties - *************************************************************************/ - [ForeignKey("MusicAlbumMetadata_MusicAlbumMetadata_Id")] - public virtual ICollection MusicAlbumMetadata { get; protected set; } - - [ForeignKey("Track_Tracks_Id")] public virtual ICollection Tracks { get; protected set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/MusicAlbumMetadata.cs b/Jellyfin.Data/Entities/Libraries/MusicAlbumMetadata.cs index f2480a5c54..cc5919bfe3 100644 --- a/Jellyfin.Data/Entities/Libraries/MusicAlbumMetadata.cs +++ b/Jellyfin.Data/Entities/Libraries/MusicAlbumMetadata.cs @@ -1,207 +1,69 @@ -#pragma warning disable CS1591 - -using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; namespace Jellyfin.Data.Entities.Libraries { - public partial class MusicAlbumMetadata : Metadata + /// + /// An entity holding the metadata for a music album. + /// + public class MusicAlbumMetadata : Metadata { - partial void Init(); - - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. - /// - protected MusicAlbumMetadata() - { - Labels = new HashSet(); - - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static MusicAlbumMetadata CreateMusicAlbumMetadataUnsafe() - { - return new MusicAlbumMetadata(); - } - /// - /// Public constructor with required data. + /// Initializes a new instance of the class. /// - /// The title or name of the object. + /// The title or name of the album. /// ISO-639-3 3-character language codes. - /// The date the object was added. - /// The date the object was last modified. - /// - public MusicAlbumMetadata(string title, string language, DateTime dateadded, DateTime datemodified, MusicAlbum _musicalbum0) + /// The music album. + public MusicAlbumMetadata(string title, string language, MusicAlbum album) : base(title, language) { - if (string.IsNullOrEmpty(title)) - { - throw new ArgumentNullException(nameof(title)); - } - - this.Title = title; - - if (string.IsNullOrEmpty(language)) - { - throw new ArgumentNullException(nameof(language)); - } - - this.Language = language; - - if (_musicalbum0 == null) - { - throw new ArgumentNullException(nameof(_musicalbum0)); - } - - _musicalbum0.MusicAlbumMetadata.Add(this); - - this.Labels = new HashSet(); + Labels = new HashSet(); - Init(); + album.MusicAlbumMetadata.Add(this); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// The title or name of the object. - /// ISO-639-3 3-character language codes. - /// The date the object was added. - /// The date the object was last modified. - /// - public static MusicAlbumMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, MusicAlbum _musicalbum0) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected MusicAlbumMetadata() { - return new MusicAlbumMetadata(title, language, dateadded, datemodified, _musicalbum0); } - /************************************************************************* - * Properties - *************************************************************************/ - - /// - /// Backing field for Barcode. - /// - protected string _Barcode; - /// - /// When provided in a partial class, allows value of Barcode to be changed before setting. - /// - partial void SetBarcode(string oldValue, ref string newValue); /// - /// When provided in a partial class, allows value of Barcode to be changed before returning. - /// - partial void GetBarcode(ref string result); - - /// - /// Max length = 255 + /// Gets or sets the barcode. /// + /// + /// Max length = 255. + /// [MaxLength(255)] [StringLength(255)] - public string Barcode - { - get - { - string value = _Barcode; - GetBarcode(ref value); - return _Barcode = value; - } + public string Barcode { get; set; } - set - { - string oldValue = _Barcode; - SetBarcode(oldValue, ref value); - if (oldValue != value) - { - _Barcode = value; - } - } - } - - /// - /// Backing field for LabelNumber. - /// - protected string _LabelNumber; /// - /// When provided in a partial class, allows value of LabelNumber to be changed before setting. - /// - partial void SetLabelNumber(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of LabelNumber to be changed before returning. - /// - partial void GetLabelNumber(ref string result); - - /// - /// Max length = 255 + /// Gets or sets the label number. /// + /// + /// Max length = 255. + /// [MaxLength(255)] [StringLength(255)] - public string LabelNumber - { - get - { - string value = _LabelNumber; - GetLabelNumber(ref value); - return _LabelNumber = value; - } - - set - { - string oldValue = _LabelNumber; - SetLabelNumber(oldValue, ref value); - if (oldValue != value) - { - _LabelNumber = value; - } - } - } - - /// - /// Backing field for Country. - /// - protected string _Country; - /// - /// When provided in a partial class, allows value of Country to be changed before setting. - /// - partial void SetCountry(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Country to be changed before returning. - /// - partial void GetCountry(ref string result); + public string LabelNumber { get; set; } /// - /// Max length = 2 + /// Gets or sets the country code. /// + /// + /// Max length = 2. + /// [MaxLength(2)] [StringLength(2)] - public string Country - { - get - { - string value = _Country; - GetCountry(ref value); - return _Country = value; - } - - set - { - string oldValue = _Country; - SetCountry(oldValue, ref value); - if (oldValue != value) - { - _Country = value; - } - } - } - - /************************************************************************* - * Navigation properties - *************************************************************************/ + public string Country { get; set; } - [ForeignKey("Company_Labels_Id")] + /// + /// Gets or sets a collection containing the labels. + /// public virtual ICollection Labels { get; protected set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/Person.cs b/Jellyfin.Data/Entities/Libraries/Person.cs index f325a07ff8..8beb3dd084 100644 --- a/Jellyfin.Data/Entities/Libraries/Person.cs +++ b/Jellyfin.Data/Entities/Libraries/Person.cs @@ -1,317 +1,103 @@ -#pragma warning disable CS1591 - using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class Person + /// + /// An entity representing a person. + /// + public class Person : IHasConcurrencyToken { - partial void Init(); - - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. - /// - protected Person() - { - Sources = new HashSet(); - - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static Person CreatePersonUnsafe() - { - return new Person(); - } - /// - /// Public constructor with required data. + /// Initializes a new instance of the class. /// - /// - /// - /// The date the object was added. - /// The date the object was last modified. - public Person(Guid urlid, string name, DateTime dateadded, DateTime datemodified) + /// The name of the person. + public Person(string name) { - this.UrlId = urlid; - if (string.IsNullOrEmpty(name)) { throw new ArgumentNullException(nameof(name)); } - this.Name = name; - - this.Sources = new HashSet(); + Name = name; + DateAdded = DateTime.UtcNow; + DateModified = DateAdded; - Init(); + Sources = new HashSet(); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// - /// - /// The date the object was added. - /// The date the object was last modified. - public static Person Create(Guid urlid, string name, DateTime dateadded, DateTime datemodified) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected Person() { - return new Person(urlid, name, dateadded, datemodified); } - /************************************************************************* - * Properties - *************************************************************************/ - - /// - /// Backing field for Id. - /// - internal int _Id; /// - /// When provided in a partial class, allows value of Id to be changed before setting. + /// Gets or sets the id. /// - partial void SetId(int oldValue, ref int newValue); - /// - /// When provided in a partial class, allows value of Id to be changed before returning. - /// - partial void GetId(ref int result); - - /// + /// /// Identity, Indexed, Required. - /// - [Key] - [Required] + /// [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public int Id - { - get - { - int value = _Id; - GetId(ref value); - return _Id = value; - } - - protected set - { - int oldValue = _Id; - SetId(oldValue, ref value); - if (oldValue != value) - { - _Id = value; - } - } - } - - /// - /// Backing field for UrlId. - /// - protected Guid _UrlId; - /// - /// When provided in a partial class, allows value of UrlId to be changed before setting. - /// - partial void SetUrlId(Guid oldValue, ref Guid newValue); - /// - /// When provided in a partial class, allows value of UrlId to be changed before returning. - /// - partial void GetUrlId(ref Guid result); - - /// - /// Required. - /// - [Required] - public Guid UrlId - { - get - { - Guid value = _UrlId; - GetUrlId(ref value); - return _UrlId = value; - } - - set - { - Guid oldValue = _UrlId; - SetUrlId(oldValue, ref value); - if (oldValue != value) - { - _UrlId = value; - } - } - } - - /// - /// Backing field for Name. - /// - protected string _Name; - /// - /// When provided in a partial class, allows value of Name to be changed before setting. - /// - partial void SetName(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Name to be changed before returning. - /// - partial void GetName(ref string result); + public int Id { get; protected set; } /// - /// Required, Max length = 1024 + /// Gets or sets the name. /// + /// + /// Required, Max length = 1024. + /// [Required] [MaxLength(1024)] [StringLength(1024)] - public string Name - { - get - { - string value = _Name; - GetName(ref value); - return _Name = value; - } - - set - { - string oldValue = _Name; - SetName(oldValue, ref value); - if (oldValue != value) - { - _Name = value; - } - } - } + public string Name { get; set; } /// - /// Backing field for SourceId. - /// - protected string _SourceId; - /// - /// When provided in a partial class, allows value of SourceId to be changed before setting. - /// - partial void SetSourceId(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of SourceId to be changed before returning. + /// Gets or sets the source id. /// - partial void GetSourceId(ref string result); + /// + /// Max length = 255. + /// + [MaxLength(256)] + [StringLength(256)] + public string SourceId { get; set; } /// - /// Max length = 255 + /// Gets or sets the date added. /// - [MaxLength(255)] - [StringLength(255)] - public string SourceId - { - get - { - string value = _SourceId; - GetSourceId(ref value); - return _SourceId = value; - } - - set - { - string oldValue = _SourceId; - SetSourceId(oldValue, ref value); - if (oldValue != value) - { - _SourceId = value; - } - } - } - - /// - /// Backing field for DateAdded. - /// - protected DateTime _DateAdded; - /// - /// When provided in a partial class, allows value of DateAdded to be changed before setting. - /// - partial void SetDateAdded(DateTime oldValue, ref DateTime newValue); - /// - /// When provided in a partial class, allows value of DateAdded to be changed before returning. - /// - partial void GetDateAdded(ref DateTime result); - - /// + /// /// Required. - /// - [Required] - public DateTime DateAdded - { - get - { - DateTime value = _DateAdded; - GetDateAdded(ref value); - return _DateAdded = value; - } - - internal set - { - DateTime oldValue = _DateAdded; - SetDateAdded(oldValue, ref value); - if (oldValue != value) - { - _DateAdded = value; - } - } - } + /// + public DateTime DateAdded { get; protected set; } /// - /// Backing field for DateModified. + /// Gets or sets the date modified. /// - protected DateTime _DateModified; - /// - /// When provided in a partial class, allows value of DateModified to be changed before setting. - /// - partial void SetDateModified(DateTime oldValue, ref DateTime newValue); - /// - /// When provided in a partial class, allows value of DateModified to be changed before returning. - /// - partial void GetDateModified(ref DateTime result); - - /// + /// /// Required. - /// - [Required] - public DateTime DateModified - { - get - { - DateTime value = _DateModified; - GetDateModified(ref value); - return _DateModified = value; - } + /// + public DateTime DateModified { get; set; } - internal set - { - DateTime oldValue = _DateModified; - SetDateModified(oldValue, ref value); - if (oldValue != value) - { - _DateModified = value; - } - } - } + /// + [ConcurrencyCheck] + public uint RowVersion { get; set; } /// - /// Required, ConcurrenyToken. + /// Gets or sets a list of metadata sources for this person. /// - [ConcurrencyCheck] - [Required] - public uint RowVersion { get; set; } + public virtual ICollection Sources { get; protected set; } + /// public void OnSavingChanges() { RowVersion++; } - - /************************************************************************* - * Navigation properties - *************************************************************************/ - [ForeignKey("MetadataProviderId_Sources_Id")] - public virtual ICollection Sources { get; protected set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/PersonRole.cs b/Jellyfin.Data/Entities/Libraries/PersonRole.cs index 04d50deaf7..5290228d6e 100644 --- a/Jellyfin.Data/Entities/Libraries/PersonRole.cs +++ b/Jellyfin.Data/Entities/Libraries/PersonRole.cs @@ -1,217 +1,98 @@ -#pragma warning disable CS1591 - using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Enums; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class PersonRole + /// + /// An entity representing a person's role in media. + /// + public class PersonRole : IHasArtwork, IHasConcurrencyToken { - partial void Init(); - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. + /// Initializes a new instance of the class. /// - protected PersonRole() + /// The role type. + /// The metadata. + public PersonRole(PersonRoleType type, Metadata metadata) { - // NOTE: This class has one-to-one associations with PersonRole. - // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other. - - Sources = new HashSet(); + Type = type; - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static PersonRole CreatePersonRoleUnsafe() - { - return new PersonRole(); - } - - /// - /// Public constructor with required data. - /// - /// - /// - public PersonRole(Enums.PersonRoleType type, Metadata _metadata0) - { - // NOTE: This class has one-to-one associations with PersonRole. - // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other. - - this.Type = type; - - if (_metadata0 == null) + if (metadata == null) { - throw new ArgumentNullException(nameof(_metadata0)); + throw new ArgumentNullException(nameof(metadata)); } - _metadata0.PersonRoles.Add(this); - - this.Sources = new HashSet(); + metadata.PersonRoles.Add(this); - Init(); + Sources = new HashSet(); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// - /// - public static PersonRole Create(Enums.PersonRoleType type, Metadata _metadata0) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected PersonRole() { - return new PersonRole(type, _metadata0); } - /************************************************************************* - * Properties - *************************************************************************/ - - /// - /// Backing field for Id. - /// - internal int _Id; - /// - /// When provided in a partial class, allows value of Id to be changed before setting. - /// - partial void SetId(int oldValue, ref int newValue); /// - /// When provided in a partial class, allows value of Id to be changed before returning. + /// Gets or sets the id. /// - partial void GetId(ref int result); - - /// + /// /// Identity, Indexed, Required. - /// - [Key] - [Required] + /// [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public int Id - { - get - { - int value = _Id; - GetId(ref value); - return _Id = value; - } - - protected set - { - int oldValue = _Id; - SetId(oldValue, ref value); - if (oldValue != value) - { - _Id = value; - } - } - } - - /// - /// Backing field for Role. - /// - protected string _Role; - /// - /// When provided in a partial class, allows value of Role to be changed before setting. - /// - partial void SetRole(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Role to be changed before returning. - /// - partial void GetRole(ref string result); + public int Id { get; protected set; } /// - /// Max length = 1024 + /// Gets or sets the name of the person's role. /// + /// + /// Max length = 1024. + /// [MaxLength(1024)] [StringLength(1024)] - public string Role - { - get - { - string value = _Role; - GetRole(ref value); - return _Role = value; - } - - set - { - string oldValue = _Role; - SetRole(oldValue, ref value); - if (oldValue != value) - { - _Role = value; - } - } - } + public string Role { get; set; } /// - /// Backing field for Type. + /// Gets or sets the person's role type. /// - protected Enums.PersonRoleType _Type; - /// - /// When provided in a partial class, allows value of Type to be changed before setting. - /// - partial void SetType(Enums.PersonRoleType oldValue, ref Enums.PersonRoleType newValue); - /// - /// When provided in a partial class, allows value of Type to be changed before returning. - /// - partial void GetType(ref Enums.PersonRoleType result); + /// + /// Required. + /// + public PersonRoleType Type { get; set; } + + /// + [ConcurrencyCheck] + public uint RowVersion { get; protected set; } /// - /// Required. + /// Gets or sets the person. /// + /// + /// Required. + /// [Required] - public Enums.PersonRoleType Type - { - get - { - Enums.PersonRoleType value = _Type; - GetType(ref value); - return _Type = value; - } + public virtual Person Person { get; set; } - set - { - Enums.PersonRoleType oldValue = _Type; - SetType(oldValue, ref value); - if (oldValue != value) - { - _Type = value; - } - } - } + /// + public virtual ICollection Artwork { get; protected set; } /// - /// Required, ConcurrenyToken. + /// Gets or sets a collection containing the metadata sources for this person role. /// - [ConcurrencyCheck] - [Required] - public uint RowVersion { get; set; } + public virtual ICollection Sources { get; protected set; } + /// public void OnSavingChanges() { RowVersion++; } - - /************************************************************************* - * Navigation properties - *************************************************************************/ - - /// - /// Required. - /// - [ForeignKey("Person_Id")] - - public virtual Person Person { get; set; } - - [ForeignKey("Artwork_Artwork_Id")] - public virtual Artwork Artwork { get; set; } - - [ForeignKey("MetadataProviderId_Sources_Id")] - public virtual ICollection Sources { get; protected set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/Photo.cs b/Jellyfin.Data/Entities/Libraries/Photo.cs index 01c39b3ead..44338a4cea 100644 --- a/Jellyfin.Data/Entities/Libraries/Photo.cs +++ b/Jellyfin.Data/Entities/Libraries/Photo.cs @@ -1,71 +1,28 @@ -#pragma warning disable CS1591 - -using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class Photo : LibraryItem + /// + /// An entity representing a photo. + /// + public class Photo : LibraryItem, IHasReleases { - partial void Init(); - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. + /// Initializes a new instance of the class. /// - protected Photo() + public Photo() { PhotoMetadata = new HashSet(); Releases = new HashSet(); - - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static Photo CreatePhotoUnsafe() - { - return new Photo(); - } - - /// - /// Public constructor with required data. - /// - /// This is whats gets displayed in the Urls and API requests. This could also be a string. - /// The date the object was added. - public Photo(Guid urlid, DateTime dateadded) - { - this.UrlId = urlid; - - this.PhotoMetadata = new HashSet(); - this.Releases = new HashSet(); - - Init(); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Gets or sets a collection containing the photo metadata. /// - /// This is whats gets displayed in the Urls and API requests. This could also be a string. - /// The date the object was added. - public static Photo Create(Guid urlid, DateTime dateadded) - { - return new Photo(urlid, dateadded); - } - - /************************************************************************* - * Properties - *************************************************************************/ - - /************************************************************************* - * Navigation properties - *************************************************************************/ - [ForeignKey("PhotoMetadata_PhotoMetadata_Id")] public virtual ICollection PhotoMetadata { get; protected set; } - [ForeignKey("Release_Releases_Id")] + /// public virtual ICollection Releases { get; protected set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/PhotoMetadata.cs b/Jellyfin.Data/Entities/Libraries/PhotoMetadata.cs index 701623fd14..1ef9dd5f9c 100644 --- a/Jellyfin.Data/Entities/Libraries/PhotoMetadata.cs +++ b/Jellyfin.Data/Entities/Libraries/PhotoMetadata.cs @@ -1,83 +1,36 @@ -#pragma warning disable CS1591 - using System; namespace Jellyfin.Data.Entities.Libraries { - public partial class PhotoMetadata : Metadata + /// + /// An entity that holds metadata for a photo. + /// + public class PhotoMetadata : Metadata { - partial void Init(); - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. + /// Initializes a new instance of the class. /// - protected PhotoMetadata() - { - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static PhotoMetadata CreatePhotoMetadataUnsafe() - { - return new PhotoMetadata(); - } - - /// - /// Public constructor with required data. - /// - /// The title or name of the object. + /// The title or name of the photo. /// ISO-639-3 3-character language codes. - /// The date the object was added. - /// The date the object was last modified. - /// - public PhotoMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Photo _photo0) + /// The photo. + public PhotoMetadata(string title, string language, Photo photo) : base(title, language) { - if (string.IsNullOrEmpty(title)) + if (photo == null) { - throw new ArgumentNullException(nameof(title)); + throw new ArgumentNullException(nameof(photo)); } - this.Title = title; - - if (string.IsNullOrEmpty(language)) - { - throw new ArgumentNullException(nameof(language)); - } - - this.Language = language; - - if (_photo0 == null) - { - throw new ArgumentNullException(nameof(_photo0)); - } - - _photo0.PhotoMetadata.Add(this); - - Init(); + photo.PhotoMetadata.Add(this); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// The title or name of the object. - /// ISO-639-3 3-character language codes. - /// The date the object was added. - /// The date the object was last modified. - /// - public static PhotoMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, Photo _photo0) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected PhotoMetadata() { - return new PhotoMetadata(title, language, dateadded, datemodified, _photo0); } - - /************************************************************************* - * Properties - *************************************************************************/ - - /************************************************************************* - * Navigation properties - *************************************************************************/ } } - diff --git a/Jellyfin.Data/Entities/Libraries/Rating.cs b/Jellyfin.Data/Entities/Libraries/Rating.cs index 31bee165af..ba054a39e0 100644 --- a/Jellyfin.Data/Entities/Libraries/Rating.cs +++ b/Jellyfin.Data/Entities/Libraries/Rating.cs @@ -1,194 +1,78 @@ -#pragma warning disable CS1591 - using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class Rating + /// + /// An entity representing a rating for an entity. + /// + public class Rating : IHasConcurrencyToken { - partial void Init(); - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. + /// Initializes a new instance of the class. /// - protected Rating() + /// The value. + /// The metadata. + public Rating(double value, Metadata metadata) { - Init(); - } + Value = value; - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static Rating CreateRatingUnsafe() - { - return new Rating(); - } - - /// - /// Public constructor with required data. - /// - /// - /// - public Rating(double value, Metadata _metadata0) - { - this.Value = value; - - if (_metadata0 == null) + if (metadata == null) { - throw new ArgumentNullException(nameof(_metadata0)); + throw new ArgumentNullException(nameof(metadata)); } - _metadata0.Ratings.Add(this); - - Init(); + metadata.Ratings.Add(this); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// - /// - public static Rating Create(double value, Metadata _metadata0) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected Rating() { - return new Rating(value, _metadata0); } - /************************************************************************* - * Properties - *************************************************************************/ - - /// - /// Backing field for Id. - /// - internal int _Id; - /// - /// When provided in a partial class, allows value of Id to be changed before setting. - /// - partial void SetId(int oldValue, ref int newValue); /// - /// When provided in a partial class, allows value of Id to be changed before returning. + /// Gets or sets the id. /// - partial void GetId(ref int result); - - /// + /// /// Identity, Indexed, Required. - /// - [Key] - [Required] + /// [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public int Id - { - get - { - int value = _Id; - GetId(ref value); - return _Id = value; - } - - protected set - { - int oldValue = _Id; - SetId(oldValue, ref value); - if (oldValue != value) - { - _Id = value; - } - } - } + public int Id { get; protected set; } /// - /// Backing field for Value. - /// - protected double _Value; - /// - /// When provided in a partial class, allows value of Value to be changed before setting. + /// Gets or sets the value. /// - partial void SetValue(double oldValue, ref double newValue); - /// - /// When provided in a partial class, allows value of Value to be changed before returning. - /// - partial void GetValue(ref double result); - - /// + /// /// Required. - /// - [Required] - public double Value - { - get - { - double value = _Value; - GetValue(ref value); - return _Value = value; - } + /// + public double Value { get; set; } - set - { - double oldValue = _Value; - SetValue(oldValue, ref value); - if (oldValue != value) - { - _Value = value; - } - } - } - - /// - /// Backing field for Votes. - /// - protected int? _Votes; - /// - /// When provided in a partial class, allows value of Votes to be changed before setting. - /// - partial void SetVotes(int? oldValue, ref int? newValue); /// - /// When provided in a partial class, allows value of Votes to be changed before returning. + /// Gets or sets the number of votes. /// - partial void GetVotes(ref int? result); - - public int? Votes - { - get - { - int? value = _Votes; - GetVotes(ref value); - return _Votes = value; - } + public int? Votes { get; set; } - set - { - int? oldValue = _Votes; - SetVotes(oldValue, ref value); - if (oldValue != value) - { - _Votes = value; - } - } - } + /// + [ConcurrencyCheck] + public uint RowVersion { get; set; } /// - /// Required, ConcurrenyToken. + /// Gets or sets the rating type. + /// If this is null it's the internal user rating. /// - [ConcurrencyCheck] - [Required] - public uint RowVersion { get; set; } + public virtual RatingSource RatingType { get; set; } + /// public void OnSavingChanges() { RowVersion++; } - - /************************************************************************* - * Navigation properties - *************************************************************************/ - - /// - /// If this is NULL it's the internal user rating. - /// - [ForeignKey("RatingSource_RatingType_Id")] - public virtual RatingSource RatingType { get; set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/RatingSource.cs b/Jellyfin.Data/Entities/Libraries/RatingSource.cs index 8204e9ff23..549f418042 100644 --- a/Jellyfin.Data/Entities/Libraries/RatingSource.cs +++ b/Jellyfin.Data/Entities/Libraries/RatingSource.cs @@ -1,239 +1,92 @@ -#pragma warning disable CS1591 - using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { /// /// This is the entity to store review ratings, not age ratings. /// - public partial class RatingSource + public class RatingSource : IHasConcurrencyToken { - partial void Init(); - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. + /// Initializes a new instance of the class. /// - protected RatingSource() + /// The minimum value. + /// The maximum value. + /// The rating. + public RatingSource(double minimumValue, double maximumValue, Rating rating) { - Init(); - } + MinimumValue = minimumValue; + MaximumValue = maximumValue; - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static RatingSource CreateRatingSourceUnsafe() - { - return new RatingSource(); - } - - /// - /// Public constructor with required data. - /// - /// - /// - /// - public RatingSource(double maximumvalue, double minimumvalue, Rating _rating0) - { - this.MaximumValue = maximumvalue; - - this.MinimumValue = minimumvalue; - - if (_rating0 == null) + if (rating == null) { - throw new ArgumentNullException(nameof(_rating0)); + throw new ArgumentNullException(nameof(rating)); } - _rating0.RatingType = this; - - Init(); + rating.RatingType = this; } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// - /// - /// - public static RatingSource Create(double maximumvalue, double minimumvalue, Rating _rating0) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected RatingSource() { - return new RatingSource(maximumvalue, minimumvalue, _rating0); } - /************************************************************************* - * Properties - *************************************************************************/ - - /// - /// Backing field for Id. - /// - internal int _Id; /// - /// When provided in a partial class, allows value of Id to be changed before setting. + /// Gets or sets the id. /// - partial void SetId(int oldValue, ref int newValue); - /// - /// When provided in a partial class, allows value of Id to be changed before returning. - /// - partial void GetId(ref int result); - - /// + /// /// Identity, Indexed, Required. - /// - [Key] - [Required] + /// [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public int Id - { - get - { - int value = _Id; - GetId(ref value); - return _Id = value; - } - - protected set - { - int oldValue = _Id; - SetId(oldValue, ref value); - if (oldValue != value) - { - _Id = value; - } - } - } - - /// - /// Backing field for Name. - /// - protected string _Name; - /// - /// When provided in a partial class, allows value of Name to be changed before setting. - /// - partial void SetName(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Name to be changed before returning. - /// - partial void GetName(ref string result); + public int Id { get; protected set; } /// - /// Max length = 1024 + /// Gets or sets the name. /// + /// + /// Max length = 1024. + /// [MaxLength(1024)] [StringLength(1024)] - public string Name - { - get - { - string value = _Name; - GetName(ref value); - return _Name = value; - } - - set - { - string oldValue = _Name; - SetName(oldValue, ref value); - if (oldValue != value) - { - _Name = value; - } - } - } + public string Name { get; set; } /// - /// Backing field for MaximumValue. + /// Gets or sets the minimum value. /// - protected double _MaximumValue; - /// - /// When provided in a partial class, allows value of MaximumValue to be changed before setting. - /// - partial void SetMaximumValue(double oldValue, ref double newValue); - /// - /// When provided in a partial class, allows value of MaximumValue to be changed before returning. - /// - partial void GetMaximumValue(ref double result); - - /// + /// /// Required. - /// - [Required] - public double MaximumValue - { - get - { - double value = _MaximumValue; - GetMaximumValue(ref value); - return _MaximumValue = value; - } - - set - { - double oldValue = _MaximumValue; - SetMaximumValue(oldValue, ref value); - if (oldValue != value) - { - _MaximumValue = value; - } - } - } + /// + public double MinimumValue { get; set; } /// - /// Backing field for MinimumValue. + /// Gets or sets the maximum value. /// - protected double _MinimumValue; - /// - /// When provided in a partial class, allows value of MinimumValue to be changed before setting. - /// - partial void SetMinimumValue(double oldValue, ref double newValue); - /// - /// When provided in a partial class, allows value of MinimumValue to be changed before returning. - /// - partial void GetMinimumValue(ref double result); - - /// + /// /// Required. - /// - [Required] - public double MinimumValue - { - get - { - double value = _MinimumValue; - GetMinimumValue(ref value); - return _MinimumValue = value; - } + /// + public double MaximumValue { get; set; } - set - { - double oldValue = _MinimumValue; - SetMinimumValue(oldValue, ref value); - if (oldValue != value) - { - _MinimumValue = value; - } - } - } + /// + [ConcurrencyCheck] + public uint RowVersion { get; set; } /// - /// Required, ConcurrenyToken. + /// Gets or sets the metadata source. /// - [ConcurrencyCheck] - [Required] - public uint RowVersion { get; set; } + public virtual MetadataProviderId Source { get; set; } + /// public void OnSavingChanges() { RowVersion++; } - - /************************************************************************* - * Navigation properties - *************************************************************************/ - [ForeignKey("MetadataProviderId_Source_Id")] - public virtual MetadataProviderId Source { get; set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/Release.cs b/Jellyfin.Data/Entities/Libraries/Release.cs index 4b42d65ec5..43c7080d79 100644 --- a/Jellyfin.Data/Entities/Libraries/Release.cs +++ b/Jellyfin.Data/Entities/Libraries/Release.cs @@ -1,219 +1,84 @@ -#pragma warning disable CS1591 - using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class Release + /// + /// An entity representing a release for a library item, eg. Director's cut vs. standard. + /// + public class Release : IHasConcurrencyToken { - partial void Init(); - - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. - /// - protected Release() - { - MediaFiles = new HashSet(); - Chapters = new HashSet(); - - Init(); - } - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. + /// Initializes a new instance of the class. /// - public static Release CreateReleaseUnsafe() - { - return new Release(); - } - - /// - /// Public constructor with required data. - /// - /// - /// - /// - /// - /// - /// - /// - public Release(string name, Movie _movie0, Episode _episode1, Track _track2, CustomItem _customitem3, Book _book4, Photo _photo5) + /// The name of this release. + /// The owner of this release. + public Release(string name, IHasReleases owner) { if (string.IsNullOrEmpty(name)) { throw new ArgumentNullException(nameof(name)); } - this.Name = name; + Name = name; - if (_movie0 == null) - { - throw new ArgumentNullException(nameof(_movie0)); - } - - _movie0.Releases.Add(this); - - if (_episode1 == null) - { - throw new ArgumentNullException(nameof(_episode1)); - } + owner?.Releases.Add(this); - _episode1.Releases.Add(this); - - if (_track2 == null) - { - throw new ArgumentNullException(nameof(_track2)); - } - - _track2.Releases.Add(this); - - if (_customitem3 == null) - { - throw new ArgumentNullException(nameof(_customitem3)); - } - - _customitem3.Releases.Add(this); - - if (_book4 == null) - { - throw new ArgumentNullException(nameof(_book4)); - } - - _book4.Releases.Add(this); - - if (_photo5 == null) - { - throw new ArgumentNullException(nameof(_photo5)); - } - - _photo5.Releases.Add(this); - - this.MediaFiles = new HashSet(); - this.Chapters = new HashSet(); - - Init(); + MediaFiles = new HashSet(); + Chapters = new HashSet(); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// - /// - /// - /// - /// - /// - /// - public static Release Create(string name, Movie _movie0, Episode _episode1, Track _track2, CustomItem _customitem3, Book _book4, Photo _photo5) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected Release() { - return new Release(name, _movie0, _episode1, _track2, _customitem3, _book4, _photo5); } - /************************************************************************* - * Properties - *************************************************************************/ - - /// - /// Backing field for Id. - /// - internal int _Id; /// - /// When provided in a partial class, allows value of Id to be changed before setting. + /// Gets or sets the id. /// - partial void SetId(int oldValue, ref int newValue); - /// - /// When provided in a partial class, allows value of Id to be changed before returning. - /// - partial void GetId(ref int result); - - /// + /// /// Identity, Indexed, Required. - /// - [Key] - [Required] + /// [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - public int Id - { - get - { - int value = _Id; - GetId(ref value); - return _Id = value; - } - - protected set - { - int oldValue = _Id; - SetId(oldValue, ref value); - if (oldValue != value) - { - _Id = value; - } - } - } - - /// - /// Backing field for Name. - /// - protected string _Name; - /// - /// When provided in a partial class, allows value of Name to be changed before setting. - /// - partial void SetName(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Name to be changed before returning. - /// - partial void GetName(ref string result); + public int Id { get; protected set; } /// - /// Required, Max length = 1024 + /// Gets or sets the name. /// + /// + /// Required, Max length = 1024. + /// [Required] [MaxLength(1024)] [StringLength(1024)] - public string Name - { - get - { - string value = _Name; - GetName(ref value); - return _Name = value; - } + public string Name { get; set; } - set - { - string oldValue = _Name; - SetName(oldValue, ref value); - if (oldValue != value) - { - _Name = value; - } - } - } + /// + [ConcurrencyCheck] + public uint RowVersion { get; set; } /// - /// Required, ConcurrenyToken. + /// Gets or sets a collection containing the media files for this release. /// - [ConcurrencyCheck] - [Required] - public uint RowVersion { get; set; } + public virtual ICollection MediaFiles { get; protected set; } + + /// + /// Gets or sets a collection containing the chapters for this release. + /// + public virtual ICollection Chapters { get; protected set; } + /// public void OnSavingChanges() { RowVersion++; } - - /************************************************************************* - * Navigation properties - *************************************************************************/ - [ForeignKey("MediaFile_MediaFiles_Id")] - public virtual ICollection MediaFiles { get; protected set; } - - [ForeignKey("Chapter_Chapters_Id")] - public virtual ICollection Chapters { get; protected set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/Season.cs b/Jellyfin.Data/Entities/Libraries/Season.cs index 90885f0e97..eef788bad2 100644 --- a/Jellyfin.Data/Entities/Libraries/Season.cs +++ b/Jellyfin.Data/Entities/Libraries/Season.cs @@ -1,119 +1,53 @@ -#pragma warning disable CS1591 - using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; namespace Jellyfin.Data.Entities.Libraries { - public partial class Season : LibraryItem + /// + /// An entity representing a season. + /// + public class Season : LibraryItem { - partial void Init(); - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. + /// Initializes a new instance of the class. /// - protected Season() + /// The series. + public Season(Series series) { - // NOTE: This class has one-to-one associations with LibraryRoot, LibraryItem and CollectionItem. - // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other. - - SeasonMetadata = new HashSet(); - Episodes = new HashSet(); - - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static Season CreateSeasonUnsafe() - { - return new Season(); - } - - /// - /// Public constructor with required data. - /// - /// This is whats gets displayed in the Urls and API requests. This could also be a string. - /// The date the object was added. - /// - public Season(Guid urlid, DateTime dateadded, Series _series0) - { - // NOTE: This class has one-to-one associations with LibraryRoot, LibraryItem and CollectionItem. - // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other. - - this.UrlId = urlid; - - if (_series0 == null) + if (series == null) { - throw new ArgumentNullException(nameof(_series0)); + throw new ArgumentNullException(nameof(series)); } - _series0.Seasons.Add(this); - - this.SeasonMetadata = new HashSet(); - this.Episodes = new HashSet(); + series.Seasons.Add(this); - Init(); + Episodes = new HashSet(); + SeasonMetadata = new HashSet(); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// This is whats gets displayed in the Urls and API requests. This could also be a string. - /// The date the object was added. - /// - public static Season Create(Guid urlid, DateTime dateadded, Series _series0) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected Season() { - return new Season(urlid, dateadded, _series0); } - /************************************************************************* - * Properties - *************************************************************************/ - /// - /// Backing field for SeasonNumber. + /// Gets or sets the season number. /// - protected int? _SeasonNumber; - /// - /// When provided in a partial class, allows value of SeasonNumber to be changed before setting. - /// - partial void SetSeasonNumber(int? oldValue, ref int? newValue); + public int? SeasonNumber { get; set; } + /// - /// When provided in a partial class, allows value of SeasonNumber to be changed before returning. + /// Gets or sets the season metadata. /// - partial void GetSeasonNumber(ref int? result); - - public int? SeasonNumber - { - get - { - int? value = _SeasonNumber; - GetSeasonNumber(ref value); - return _SeasonNumber = value; - } - - set - { - int? oldValue = _SeasonNumber; - SetSeasonNumber(oldValue, ref value); - if (oldValue != value) - { - _SeasonNumber = value; - } - } - } - - /************************************************************************* - * Navigation properties - *************************************************************************/ - [ForeignKey("SeasonMetadata_SeasonMetadata_Id")] public virtual ICollection SeasonMetadata { get; protected set; } - [ForeignKey("Episode_Episodes_Id")] + /// + /// Gets or sets a collection containing the number of episodes. + /// public virtual ICollection Episodes { get; protected set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/SeasonMetadata.cs b/Jellyfin.Data/Entities/Libraries/SeasonMetadata.cs index 28105fe2cc..eedeb089e8 100644 --- a/Jellyfin.Data/Entities/Libraries/SeasonMetadata.cs +++ b/Jellyfin.Data/Entities/Libraries/SeasonMetadata.cs @@ -1,122 +1,47 @@ -#pragma warning disable CS1591 - using System; using System.ComponentModel.DataAnnotations; namespace Jellyfin.Data.Entities.Libraries { - public partial class SeasonMetadata : Metadata + /// + /// An entity that holds metadata for seasons. + /// + public class SeasonMetadata : Metadata { - partial void Init(); - - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. - /// - protected SeasonMetadata() - { - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static SeasonMetadata CreateSeasonMetadataUnsafe() - { - return new SeasonMetadata(); - } - /// - /// Public constructor with required data. + /// Initializes a new instance of the class. /// /// The title or name of the object. /// ISO-639-3 3-character language codes. - /// The date the object was added. - /// The date the object was last modified. - /// - public SeasonMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Season _season0) + /// The season. + public SeasonMetadata(string title, string language, Season season) : base(title, language) { - if (string.IsNullOrEmpty(title)) - { - throw new ArgumentNullException(nameof(title)); - } - - this.Title = title; - - if (string.IsNullOrEmpty(language)) - { - throw new ArgumentNullException(nameof(language)); - } - - this.Language = language; - - if (_season0 == null) + if (season == null) { - throw new ArgumentNullException(nameof(_season0)); + throw new ArgumentNullException(nameof(season)); } - _season0.SeasonMetadata.Add(this); - - Init(); + season.SeasonMetadata.Add(this); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// The title or name of the object. - /// ISO-639-3 3-character language codes. - /// The date the object was added. - /// The date the object was last modified. - /// - public static SeasonMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, Season _season0) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected SeasonMetadata() { - return new SeasonMetadata(title, language, dateadded, datemodified, _season0); } - /************************************************************************* - * Properties - *************************************************************************/ - - /// - /// Backing field for Outline. - /// - protected string _Outline; - /// - /// When provided in a partial class, allows value of Outline to be changed before setting. - /// - partial void SetOutline(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Outline to be changed before returning. - /// - partial void GetOutline(ref string result); - /// - /// Max length = 1024 + /// Gets or sets the outline. /// + /// + /// Max length = 1024. + /// [MaxLength(1024)] [StringLength(1024)] - public string Outline - { - get - { - string value = _Outline; - GetOutline(ref value); - return _Outline = value; - } - - set - { - string oldValue = _Outline; - SetOutline(oldValue, ref value); - if (oldValue != value) - { - _Outline = value; - } - } - } - - /************************************************************************* - * Navigation properties - *************************************************************************/ + public string Outline { get; set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/Series.cs b/Jellyfin.Data/Entities/Libraries/Series.cs index a137f0f687..e959c1fe00 100644 --- a/Jellyfin.Data/Entities/Libraries/Series.cs +++ b/Jellyfin.Data/Entities/Libraries/Series.cs @@ -1,165 +1,46 @@ -#pragma warning disable CS1591 - using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; namespace Jellyfin.Data.Entities.Libraries { - public partial class Series : LibraryItem + /// + /// An entity representing a a series. + /// + public class Series : LibraryItem { - partial void Init(); - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. + /// Initializes a new instance of the class. /// - protected Series() + public Series() { - SeriesMetadata = new HashSet(); + DateAdded = DateTime.UtcNow; Seasons = new HashSet(); - - Init(); + SeriesMetadata = new HashSet(); } /// - /// Public constructor with required data. + /// Gets or sets the days of week. /// - /// This is whats gets displayed in the Urls and API requests. This could also be a string. - /// The date the object was added. - public Series(Guid urlid, DateTime dateadded) - { - this.UrlId = urlid; - - this.SeriesMetadata = new HashSet(); - this.Seasons = new HashSet(); - - Init(); - } + public DayOfWeek? AirsDayOfWeek { get; set; } /// - /// Static create function (for use in LINQ queries, etc.) + /// Gets or sets the time the show airs, ignore the date portion. /// - /// This is whats gets displayed in the Urls and API requests. This could also be a string. - /// The date the object was added. - public static Series Create(Guid urlid, DateTime dateadded) - { - return new Series(urlid, dateadded); - } + public DateTimeOffset? AirsTime { get; set; } - /************************************************************************* - * Properties - *************************************************************************/ - - /// - /// Backing field for AirsDayOfWeek. - /// - protected DayOfWeek? _AirsDayOfWeek; /// - /// When provided in a partial class, allows value of AirsDayOfWeek to be changed before setting. + /// Gets or sets the date the series first aired. /// - partial void SetAirsDayOfWeek(DayOfWeek? oldValue, ref DayOfWeek? newValue); - /// - /// When provided in a partial class, allows value of AirsDayOfWeek to be changed before returning. - /// - partial void GetAirsDayOfWeek(ref DayOfWeek? result); + public DateTime? FirstAired { get; set; } - public DayOfWeek? AirsDayOfWeek - { - get - { - DayOfWeek? value = _AirsDayOfWeek; - GetAirsDayOfWeek(ref value); - return _AirsDayOfWeek = value; - } - - set - { - DayOfWeek? oldValue = _AirsDayOfWeek; - SetAirsDayOfWeek(oldValue, ref value); - if (oldValue != value) - { - _AirsDayOfWeek = value; - } - } - } - - /// - /// Backing field for AirsTime. - /// - protected DateTimeOffset? _AirsTime; /// - /// When provided in a partial class, allows value of AirsTime to be changed before setting. + /// Gets or sets a collection containing the series metadata. /// - partial void SetAirsTime(DateTimeOffset? oldValue, ref DateTimeOffset? newValue); - /// - /// When provided in a partial class, allows value of AirsTime to be changed before returning. - /// - partial void GetAirsTime(ref DateTimeOffset? result); - - /// - /// The time the show airs, ignore the date portion. - /// - public DateTimeOffset? AirsTime - { - get - { - DateTimeOffset? value = _AirsTime; - GetAirsTime(ref value); - return _AirsTime = value; - } - - set - { - DateTimeOffset? oldValue = _AirsTime; - SetAirsTime(oldValue, ref value); - if (oldValue != value) - { - _AirsTime = value; - } - } - } + public virtual ICollection SeriesMetadata { get; protected set; } /// - /// Backing field for FirstAired. - /// - protected DateTimeOffset? _FirstAired; - /// - /// When provided in a partial class, allows value of FirstAired to be changed before setting. + /// Gets or sets a collection containing the seasons. /// - partial void SetFirstAired(DateTimeOffset? oldValue, ref DateTimeOffset? newValue); - /// - /// When provided in a partial class, allows value of FirstAired to be changed before returning. - /// - partial void GetFirstAired(ref DateTimeOffset? result); - - public DateTimeOffset? FirstAired - { - get - { - DateTimeOffset? value = _FirstAired; - GetFirstAired(ref value); - return _FirstAired = value; - } - - set - { - DateTimeOffset? oldValue = _FirstAired; - SetFirstAired(oldValue, ref value); - if (oldValue != value) - { - _FirstAired = value; - } - } - } - - /************************************************************************* - * Navigation properties - *************************************************************************/ - [ForeignKey("SeriesMetadata_SeriesMetadata_Id")] - public virtual ICollection SeriesMetadata { get; protected set; } - - [ForeignKey("Season_Seasons_Id")] public virtual ICollection Seasons { get; protected set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs b/Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs index 6e61da1e6c..898f3006dc 100644 --- a/Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs +++ b/Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs @@ -1,244 +1,91 @@ -#pragma warning disable CS1591 - using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class SeriesMetadata : Metadata + /// + /// An entity representing series metadata. + /// + public class SeriesMetadata : Metadata, IHasCompanies { - partial void Init(); - - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. - /// - protected SeriesMetadata() - { - Networks = new HashSet(); - - Init(); - } - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static SeriesMetadata CreateSeriesMetadataUnsafe() - { - return new SeriesMetadata(); - } - - /// - /// Public constructor with required data. + /// Initializes a new instance of the class. /// /// The title or name of the object. /// ISO-639-3 3-character language codes. - /// The date the object was added. - /// The date the object was last modified. - /// - public SeriesMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Series _series0) + /// The series. + public SeriesMetadata(string title, string language, Series series) : base(title, language) { - if (string.IsNullOrEmpty(title)) - { - throw new ArgumentNullException(nameof(title)); - } - - this.Title = title; - - if (string.IsNullOrEmpty(language)) - { - throw new ArgumentNullException(nameof(language)); - } - - this.Language = language; - - if (_series0 == null) + if (series == null) { - throw new ArgumentNullException(nameof(_series0)); + throw new ArgumentNullException(nameof(series)); } - _series0.SeriesMetadata.Add(this); - - this.Networks = new HashSet(); + series.SeriesMetadata.Add(this); - Init(); + Networks = new HashSet(); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// The title or name of the object. - /// ISO-639-3 3-character language codes. - /// The date the object was added. - /// The date the object was last modified. - /// - public static SeriesMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, Series _series0) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected SeriesMetadata() { - return new SeriesMetadata(title, language, dateadded, datemodified, _series0); } - /************************************************************************* - * Properties - *************************************************************************/ - - /// - /// Backing field for Outline. - /// - protected string _Outline; - /// - /// When provided in a partial class, allows value of Outline to be changed before setting. - /// - partial void SetOutline(string oldValue, ref string newValue); /// - /// When provided in a partial class, allows value of Outline to be changed before returning. - /// - partial void GetOutline(ref string result); - - /// - /// Max length = 1024 + /// Gets or sets the outline. /// + /// + /// Max length = 1024. + /// [MaxLength(1024)] [StringLength(1024)] - public string Outline - { - get - { - string value = _Outline; - GetOutline(ref value); - return _Outline = value; - } - - set - { - string oldValue = _Outline; - SetOutline(oldValue, ref value); - if (oldValue != value) - { - _Outline = value; - } - } - } + public string Outline { get; set; } /// - /// Backing field for Plot. - /// - protected string _Plot; - /// - /// When provided in a partial class, allows value of Plot to be changed before setting. - /// - partial void SetPlot(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Plot to be changed before returning. - /// - partial void GetPlot(ref string result); - - /// - /// Max length = 65535 + /// Gets or sets the plot. /// + /// + /// Max length = 65535. + /// [MaxLength(65535)] [StringLength(65535)] - public string Plot - { - get - { - string value = _Plot; - GetPlot(ref value); - return _Plot = value; - } + public string Plot { get; set; } - set - { - string oldValue = _Plot; - SetPlot(oldValue, ref value); - if (oldValue != value) - { - _Plot = value; - } - } - } - - /// - /// Backing field for Tagline. - /// - protected string _Tagline; /// - /// When provided in a partial class, allows value of Tagline to be changed before setting. - /// - partial void SetTagline(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Tagline to be changed before returning. - /// - partial void GetTagline(ref string result); - - /// - /// Max length = 1024 + /// Gets or sets the tagline. /// + /// + /// Max length = 1024. + /// [MaxLength(1024)] [StringLength(1024)] - public string Tagline - { - get - { - string value = _Tagline; - GetTagline(ref value); - return _Tagline = value; - } - - set - { - string oldValue = _Tagline; - SetTagline(oldValue, ref value); - if (oldValue != value) - { - _Tagline = value; - } - } - } - - /// - /// Backing field for Country. - /// - protected string _Country; - /// - /// When provided in a partial class, allows value of Country to be changed before setting. - /// - partial void SetCountry(string oldValue, ref string newValue); - /// - /// When provided in a partial class, allows value of Country to be changed before returning. - /// - partial void GetCountry(ref string result); + public string Tagline { get; set; } /// - /// Max length = 2 + /// Gets or sets the country code. /// + /// + /// Max length = 2. + /// [MaxLength(2)] [StringLength(2)] - public string Country - { - get - { - string value = _Country; - GetCountry(ref value); - return _Country = value; - } + public string Country { get; set; } - set - { - string oldValue = _Country; - SetCountry(oldValue, ref value); - if (oldValue != value) - { - _Country = value; - } - } - } - - /************************************************************************* - * Navigation properties - *************************************************************************/ - [ForeignKey("Company_Networks_Id")] + /// + /// Gets or sets a collection containing the networks. + /// public virtual ICollection Networks { get; protected set; } + + /// + [NotMapped] + public ICollection Companies => Networks; } } - diff --git a/Jellyfin.Data/Entities/Libraries/Track.cs b/Jellyfin.Data/Entities/Libraries/Track.cs index cdcc22d71a..09ce82a9b4 100644 --- a/Jellyfin.Data/Entities/Libraries/Track.cs +++ b/Jellyfin.Data/Entities/Libraries/Track.cs @@ -1,120 +1,52 @@ -#pragma warning disable CS1591 - using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities.Libraries { - public partial class Track : LibraryItem + /// + /// An entity representing a track. + /// + public class Track : LibraryItem, IHasReleases { - partial void Init(); - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. + /// Initializes a new instance of the class. /// - protected Track() + /// The album. + public Track(MusicAlbum album) { - // NOTE: This class has one-to-one associations with LibraryRoot, LibraryItem and CollectionItem. - // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other. - - Releases = new HashSet(); - TrackMetadata = new HashSet(); - - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static Track CreateTrackUnsafe() - { - return new Track(); - } - - /// - /// Public constructor with required data. - /// - /// This is whats gets displayed in the Urls and API requests. This could also be a string. - /// The date the object was added. - /// - public Track(Guid urlid, DateTime dateadded, MusicAlbum _musicalbum0) - { - // NOTE: This class has one-to-one associations with LibraryRoot, LibraryItem and CollectionItem. - // One-to-one associations are not validated in constructors since this causes a scenario where each one must be constructed before the other. - - this.UrlId = urlid; - - if (_musicalbum0 == null) + if (album == null) { - throw new ArgumentNullException(nameof(_musicalbum0)); + throw new ArgumentNullException(nameof(album)); } - _musicalbum0.Tracks.Add(this); - - this.Releases = new HashSet(); - this.TrackMetadata = new HashSet(); + album.Tracks.Add(this); - Init(); + Releases = new HashSet(); + TrackMetadata = new HashSet(); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// This is whats gets displayed in the Urls and API requests. This could also be a string. - /// The date the object was added. - /// - public static Track Create(Guid urlid, DateTime dateadded, MusicAlbum _musicalbum0) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected Track() { - return new Track(urlid, dateadded, _musicalbum0); } - /************************************************************************* - * Properties - *************************************************************************/ - /// - /// Backing field for TrackNumber. + /// Gets or sets the track number. /// - protected int? _TrackNumber; - /// - /// When provided in a partial class, allows value of TrackNumber to be changed before setting. - /// - partial void SetTrackNumber(int? oldValue, ref int? newValue); - /// - /// When provided in a partial class, allows value of TrackNumber to be changed before returning. - /// - partial void GetTrackNumber(ref int? result); + public int? TrackNumber { get; set; } - public int? TrackNumber - { - get - { - int? value = _TrackNumber; - GetTrackNumber(ref value); - return _TrackNumber = value; - } - - set - { - int? oldValue = _TrackNumber; - SetTrackNumber(oldValue, ref value); - if (oldValue != value) - { - _TrackNumber = value; - } - } - } - - /************************************************************************* - * Navigation properties - *************************************************************************/ - - [ForeignKey("Release_Releases_Id")] + /// public virtual ICollection Releases { get; protected set; } - [ForeignKey("TrackMetadata_TrackMetadata_Id")] + /// + /// Gets or sets a collection containing the track metadata. + /// public virtual ICollection TrackMetadata { get; protected set; } } } - diff --git a/Jellyfin.Data/Entities/Libraries/TrackMetadata.cs b/Jellyfin.Data/Entities/Libraries/TrackMetadata.cs index 5c356c768e..048068a1a3 100644 --- a/Jellyfin.Data/Entities/Libraries/TrackMetadata.cs +++ b/Jellyfin.Data/Entities/Libraries/TrackMetadata.cs @@ -1,83 +1,36 @@ -#pragma warning disable CS1591 - using System; namespace Jellyfin.Data.Entities.Libraries { - public partial class TrackMetadata : Metadata + /// + /// An entity holding metadata for a track. + /// + public class TrackMetadata : Metadata { - partial void Init(); - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. - /// - protected TrackMetadata() - { - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static TrackMetadata CreateTrackMetadataUnsafe() - { - return new TrackMetadata(); - } - - /// - /// Public constructor with required data. + /// Initializes a new instance of the class. /// /// The title or name of the object. /// ISO-639-3 3-character language codes. - /// The date the object was added. - /// The date the object was last modified. - /// - public TrackMetadata(string title, string language, DateTime dateadded, DateTime datemodified, Track _track0) + /// The track. + public TrackMetadata(string title, string language, Track track) : base(title, language) { - if (string.IsNullOrEmpty(title)) - { - throw new ArgumentNullException(nameof(title)); - } - - this.Title = title; - - if (string.IsNullOrEmpty(language)) - { - throw new ArgumentNullException(nameof(language)); - } - - this.Language = language; - - if (_track0 == null) + if (track == null) { - throw new ArgumentNullException(nameof(_track0)); + throw new ArgumentNullException(nameof(track)); } - _track0.TrackMetadata.Add(this); - - Init(); + track.TrackMetadata.Add(this); } /// - /// Static create function (for use in LINQ queries, etc.) + /// Initializes a new instance of the class. /// - /// The title or name of the object. - /// ISO-639-3 3-character language codes. - /// The date the object was added. - /// The date the object was last modified. - /// - public static TrackMetadata Create(string title, string language, DateTime dateadded, DateTime datemodified, Track _track0) + /// + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected TrackMetadata() { - return new TrackMetadata(title, language, dateadded, datemodified, _track0); } - - /************************************************************************* - * Properties - *************************************************************************/ - - /************************************************************************* - * Navigation properties - *************************************************************************/ } } - diff --git a/Jellyfin.Data/Entities/Permission.cs b/Jellyfin.Data/Entities/Permission.cs index af3270a880..c0f67f8363 100644 --- a/Jellyfin.Data/Entities/Permission.cs +++ b/Jellyfin.Data/Entities/Permission.cs @@ -3,13 +3,14 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using Jellyfin.Data.Enums; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities { /// /// An entity representing whether the associated user has a specific permission. /// - public partial class Permission : ISavingChanges + public partial class Permission : IHasConcurrencyToken { /// /// Initializes a new instance of the class. diff --git a/Jellyfin.Data/Entities/Preference.cs b/Jellyfin.Data/Entities/Preference.cs index 0ca9d7eff4..1797f0a401 100644 --- a/Jellyfin.Data/Entities/Preference.cs +++ b/Jellyfin.Data/Entities/Preference.cs @@ -2,13 +2,14 @@ using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using Jellyfin.Data.Enums; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities { /// /// An entity representing a preference attached to a user or group. /// - public class Preference : ISavingChanges + public class Preference : IHasConcurrencyToken { /// /// Initializes a new instance of the class. diff --git a/Jellyfin.Data/Entities/User.cs b/Jellyfin.Data/Entities/User.cs index 8c720d85be..7ea1f44986 100644 --- a/Jellyfin.Data/Entities/User.cs +++ b/Jellyfin.Data/Entities/User.cs @@ -8,13 +8,14 @@ using System.Globalization; using System.Linq; using System.Text.Json.Serialization; using Jellyfin.Data.Enums; +using Jellyfin.Data.Interfaces; namespace Jellyfin.Data.Entities { /// /// An entity representing a user. /// - public partial class User : IHasPermissions, ISavingChanges + public partial class User : IHasPermissions, IHasConcurrencyToken { /// /// The values being delimited here are Guids, so commas work as they do not appear in Guids. diff --git a/Jellyfin.Data/IHasPermissions.cs b/Jellyfin.Data/IHasPermissions.cs deleted file mode 100644 index 3be72259ad..0000000000 --- a/Jellyfin.Data/IHasPermissions.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Collections.Generic; -using Jellyfin.Data.Entities; -using Jellyfin.Data.Enums; - -namespace Jellyfin.Data -{ - /// - /// An abstraction representing an entity that has permissions. - /// - public interface IHasPermissions - { - /// - /// Gets a collection containing this entity's permissions. - /// - ICollection Permissions { get; } - - /// - /// Checks whether this entity has the specified permission kind. - /// - /// The kind of permission. - /// true if this entity has the specified permission, false otherwise. - bool HasPermission(PermissionKind kind); - - /// - /// Sets the specified permission to the provided value. - /// - /// The kind of permission. - /// The value to set. - void SetPermission(PermissionKind kind, bool value); - } -} diff --git a/Jellyfin.Data/ISavingChanges.cs b/Jellyfin.Data/ISavingChanges.cs deleted file mode 100644 index f392dae6a0..0000000000 --- a/Jellyfin.Data/ISavingChanges.cs +++ /dev/null @@ -1,9 +0,0 @@ -#pragma warning disable CS1591 - -namespace Jellyfin.Data -{ - public interface ISavingChanges - { - void OnSavingChanges(); - } -} diff --git a/Jellyfin.Data/Interfaces/IHasArtwork.cs b/Jellyfin.Data/Interfaces/IHasArtwork.cs new file mode 100644 index 0000000000..a4d9c54af4 --- /dev/null +++ b/Jellyfin.Data/Interfaces/IHasArtwork.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using Jellyfin.Data.Entities.Libraries; + +namespace Jellyfin.Data.Interfaces +{ + /// + /// An interface abstracting an entity that has artwork. + /// + public interface IHasArtwork + { + /// + /// Gets a collection containing this entity's artwork. + /// + ICollection Artwork { get; } + } +} diff --git a/Jellyfin.Data/Interfaces/IHasCompanies.cs b/Jellyfin.Data/Interfaces/IHasCompanies.cs new file mode 100644 index 0000000000..8f19ce04fa --- /dev/null +++ b/Jellyfin.Data/Interfaces/IHasCompanies.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using Jellyfin.Data.Entities.Libraries; + +namespace Jellyfin.Data.Interfaces +{ + /// + /// An abstraction representing an entity that has companies. + /// + public interface IHasCompanies + { + /// + /// Gets a collection containing this entity's companies. + /// + ICollection Companies { get; } + } +} diff --git a/Jellyfin.Data/Interfaces/IHasConcurrencyToken.cs b/Jellyfin.Data/Interfaces/IHasConcurrencyToken.cs new file mode 100644 index 0000000000..2c4091493e --- /dev/null +++ b/Jellyfin.Data/Interfaces/IHasConcurrencyToken.cs @@ -0,0 +1,18 @@ +namespace Jellyfin.Data.Interfaces +{ + /// + /// An interface abstracting an entity that has a concurrency token. + /// + public interface IHasConcurrencyToken + { + /// + /// Gets the version of this row. Acts as a concurrency token. + /// + uint RowVersion { get; } + + /// + /// Called when saving changes to this entity. + /// + void OnSavingChanges(); + } +} diff --git a/Jellyfin.Data/Interfaces/IHasPermissions.cs b/Jellyfin.Data/Interfaces/IHasPermissions.cs new file mode 100644 index 0000000000..3be72259ad --- /dev/null +++ b/Jellyfin.Data/Interfaces/IHasPermissions.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using Jellyfin.Data.Entities; +using Jellyfin.Data.Enums; + +namespace Jellyfin.Data +{ + /// + /// An abstraction representing an entity that has permissions. + /// + public interface IHasPermissions + { + /// + /// Gets a collection containing this entity's permissions. + /// + ICollection Permissions { get; } + + /// + /// Checks whether this entity has the specified permission kind. + /// + /// The kind of permission. + /// true if this entity has the specified permission, false otherwise. + bool HasPermission(PermissionKind kind); + + /// + /// Sets the specified permission to the provided value. + /// + /// The kind of permission. + /// The value to set. + void SetPermission(PermissionKind kind, bool value); + } +} diff --git a/Jellyfin.Data/Interfaces/IHasReleases.cs b/Jellyfin.Data/Interfaces/IHasReleases.cs new file mode 100644 index 0000000000..3b615893ed --- /dev/null +++ b/Jellyfin.Data/Interfaces/IHasReleases.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using Jellyfin.Data.Entities.Libraries; + +namespace Jellyfin.Data.Interfaces +{ + /// + /// An abstraction representing an entity that has releases. + /// + public interface IHasReleases + { + /// + /// Gets a collection containing this entity's releases. + /// + ICollection Releases { get; } + } +} diff --git a/Jellyfin.Server.Implementations/JellyfinDb.cs b/Jellyfin.Server.Implementations/JellyfinDb.cs index 7d864ebc69..08e4db3880 100644 --- a/Jellyfin.Server.Implementations/JellyfinDb.cs +++ b/Jellyfin.Server.Implementations/JellyfinDb.cs @@ -2,8 +2,8 @@ using System; using System.Linq; -using Jellyfin.Data; using Jellyfin.Data.Entities; +using Jellyfin.Data.Interfaces; using Microsoft.EntityFrameworkCore; namespace Jellyfin.Server.Implementations @@ -130,7 +130,7 @@ namespace Jellyfin.Server.Implementations foreach (var saveEntity in ChangeTracker.Entries() .Where(e => e.State == EntityState.Modified) .Select(entry => entry.Entity) - .OfType()) + .OfType()) { saveEntity.OnSavingChanges(); } -- cgit v1.2.3 From db46a9e7c883c2008055a7c75905c0efe42d5677 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 5 Sep 2020 17:54:34 -0400 Subject: Clean up JellyfinDb and fix display preferences index. --- Jellyfin.Server.Implementations/JellyfinDb.cs | 40 +++------------------------ 1 file changed, 4 insertions(+), 36 deletions(-) (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/JellyfinDb.cs b/Jellyfin.Server.Implementations/JellyfinDb.cs index 08e4db3880..92636daa3f 100644 --- a/Jellyfin.Server.Implementations/JellyfinDb.cs +++ b/Jellyfin.Server.Implementations/JellyfinDb.cs @@ -1,6 +1,5 @@ #pragma warning disable CS1591 -using System; using System.Linq; using Jellyfin.Data.Entities; using Jellyfin.Data.Interfaces; @@ -9,7 +8,7 @@ using Microsoft.EntityFrameworkCore; namespace Jellyfin.Server.Implementations { /// - public partial class JellyfinDb : DbContext + public class JellyfinDb : DbContext { /// /// Initializes a new instance of the class. @@ -138,47 +137,16 @@ namespace Jellyfin.Server.Implementations return base.SaveChanges(); } - /// - public override void Dispose() - { - foreach (var entry in ChangeTracker.Entries()) - { - entry.State = EntityState.Detached; - } - - GC.SuppressFinalize(this); - base.Dispose(); - } - - /// - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - { - CustomInit(optionsBuilder); - } - /// protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); - OnModelCreatingImpl(modelBuilder); modelBuilder.HasDefaultSchema("jellyfin"); - /*modelBuilder.Entity().HasIndex(t => t.Kind); - - modelBuilder.Entity().HasIndex(t => t.Name) - .IsUnique(); - - modelBuilder.Entity().HasIndex(t => t.UrlId) - .IsUnique();*/ - - OnModelCreatedImpl(modelBuilder); + modelBuilder.Entity() + .HasIndex(entity => new { entity.UserId, entity.Client }) + .IsUnique(); } - - partial void CustomInit(DbContextOptionsBuilder optionsBuilder); - - partial void OnModelCreatingImpl(ModelBuilder modelBuilder); - - partial void OnModelCreatedImpl(ModelBuilder modelBuilder); } } -- cgit v1.2.3 From 46c705b54502ba72abbe459c0e7dd26f9d95ffdb Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 5 Sep 2020 17:55:02 -0400 Subject: Generate migration for display preferences fix. --- Jellyfin.Server.Implementations/JellyfinDb.cs | 4 + ...05220533_FixDisplayPreferencesIndex.Designer.cs | 461 +++++++++++++++++++++ .../20200905220533_FixDisplayPreferencesIndex.cs | 51 +++ .../Migrations/JellyfinDbModelSnapshot.cs | 6 +- 4 files changed, 520 insertions(+), 2 deletions(-) create mode 100644 Jellyfin.Server.Implementations/Migrations/20200905220533_FixDisplayPreferencesIndex.Designer.cs create mode 100644 Jellyfin.Server.Implementations/Migrations/20200905220533_FixDisplayPreferencesIndex.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/JellyfinDb.cs b/Jellyfin.Server.Implementations/JellyfinDb.cs index 92636daa3f..45e71f16eb 100644 --- a/Jellyfin.Server.Implementations/JellyfinDb.cs +++ b/Jellyfin.Server.Implementations/JellyfinDb.cs @@ -144,6 +144,10 @@ namespace Jellyfin.Server.Implementations modelBuilder.HasDefaultSchema("jellyfin"); + modelBuilder.Entity() + .HasIndex(entity => entity.UserId) + .IsUnique(false); + modelBuilder.Entity() .HasIndex(entity => new { entity.UserId, entity.Client }) .IsUnique(); diff --git a/Jellyfin.Server.Implementations/Migrations/20200905220533_FixDisplayPreferencesIndex.Designer.cs b/Jellyfin.Server.Implementations/Migrations/20200905220533_FixDisplayPreferencesIndex.Designer.cs new file mode 100644 index 0000000000..2234f9d5fd --- /dev/null +++ b/Jellyfin.Server.Implementations/Migrations/20200905220533_FixDisplayPreferencesIndex.Designer.cs @@ -0,0 +1,461 @@ +#pragma warning disable CS1591 + +// +using System; +using Jellyfin.Server.Implementations; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Jellyfin.Server.Implementations.Migrations +{ + [DbContext(typeof(JellyfinDb))] + [Migration("20200905220533_FixDisplayPreferencesIndex")] + partial class FixDisplayPreferencesIndex + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("jellyfin") + .HasAnnotation("ProductVersion", "3.1.7"); + + modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DayOfWeek") + .HasColumnType("INTEGER"); + + b.Property("EndHour") + .HasColumnType("REAL"); + + b.Property("StartHour") + .HasColumnType("REAL"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AccessSchedules"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateCreated") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("LogSeverity") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(512); + + b.Property("Overview") + .HasColumnType("TEXT") + .HasMaxLength(512); + + b.Property("RowVersion") + .IsConcurrencyToken() + .HasColumnType("INTEGER"); + + b.Property("ShortOverview") + .HasColumnType("TEXT") + .HasMaxLength(512); + + b.Property("Type") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("ActivityLogs"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChromecastVersion") + .HasColumnType("INTEGER"); + + b.Property("Client") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("DashboardTheme") + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("EnableNextVideoInfoOverlay") + .HasColumnType("INTEGER"); + + b.Property("IndexBy") + .HasColumnType("INTEGER"); + + b.Property("ScrollDirection") + .HasColumnType("INTEGER"); + + b.Property("ShowBackdrop") + .HasColumnType("INTEGER"); + + b.Property("ShowSidebar") + .HasColumnType("INTEGER"); + + b.Property("SkipBackwardLength") + .HasColumnType("INTEGER"); + + b.Property("SkipForwardLength") + .HasColumnType("INTEGER"); + + b.Property("TvHome") + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("UserId", "Client") + .IsUnique(); + + b.ToTable("DisplayPreferences"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DisplayPreferencesId") + .HasColumnType("INTEGER"); + + b.Property("Order") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("DisplayPreferencesId"); + + b.ToTable("HomeSection"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("LastModified") + .HasColumnType("TEXT"); + + b.Property("Path") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(512); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("ImageInfos"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Client") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("IndexBy") + .HasColumnType("INTEGER"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.Property("RememberIndexing") + .HasColumnType("INTEGER"); + + b.Property("RememberSorting") + .HasColumnType("INTEGER"); + + b.Property("SortBy") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(64); + + b.Property("SortOrder") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("ViewType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("ItemDisplayPreferences"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Kind") + .HasColumnType("INTEGER"); + + b.Property("Permission_Permissions_Guid") + .HasColumnType("TEXT"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("Permission_Permissions_Guid"); + + b.ToTable("Permissions"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Kind") + .HasColumnType("INTEGER"); + + b.Property("Preference_Preferences_Guid") + .HasColumnType("TEXT"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .HasColumnType("INTEGER"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(65535); + + b.HasKey("Id"); + + b.HasIndex("Preference_Preferences_Guid"); + + b.ToTable("Preferences"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("AudioLanguagePreference") + .HasColumnType("TEXT") + .HasMaxLength(255); + + b.Property("AuthenticationProviderId") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(255); + + b.Property("DisplayCollectionsView") + .HasColumnType("INTEGER"); + + b.Property("DisplayMissingEpisodes") + .HasColumnType("INTEGER"); + + b.Property("EasyPassword") + .HasColumnType("TEXT") + .HasMaxLength(65535); + + b.Property("EnableAutoLogin") + .HasColumnType("INTEGER"); + + b.Property("EnableLocalPassword") + .HasColumnType("INTEGER"); + + b.Property("EnableNextEpisodeAutoPlay") + .HasColumnType("INTEGER"); + + b.Property("EnableUserPreferenceAccess") + .HasColumnType("INTEGER"); + + b.Property("HidePlayedInLatest") + .HasColumnType("INTEGER"); + + b.Property("InternalId") + .HasColumnType("INTEGER"); + + b.Property("InvalidLoginAttemptCount") + .HasColumnType("INTEGER"); + + b.Property("LastActivityDate") + .HasColumnType("TEXT"); + + b.Property("LastLoginDate") + .HasColumnType("TEXT"); + + b.Property("LoginAttemptsBeforeLockout") + .HasColumnType("INTEGER"); + + b.Property("MaxParentalAgeRating") + .HasColumnType("INTEGER"); + + b.Property("MustUpdatePassword") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT") + .HasMaxLength(65535); + + b.Property("PasswordResetProviderId") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(255); + + b.Property("PlayDefaultAudioTrack") + .HasColumnType("INTEGER"); + + b.Property("RememberAudioSelections") + .HasColumnType("INTEGER"); + + b.Property("RememberSubtitleSelections") + .HasColumnType("INTEGER"); + + b.Property("RemoteClientBitrateLimit") + .HasColumnType("INTEGER"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .HasColumnType("INTEGER"); + + b.Property("SubtitleLanguagePreference") + .HasColumnType("TEXT") + .HasMaxLength(255); + + b.Property("SubtitleMode") + .HasColumnType("INTEGER"); + + b.Property("SyncPlayAccess") + .HasColumnType("INTEGER"); + + b.Property("Username") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(255); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithMany("AccessSchedules") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithOne("DisplayPreferences") + .HasForeignKey("Jellyfin.Data.Entities.DisplayPreferences", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => + { + b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) + .WithMany("HomeSections") + .HasForeignKey("DisplayPreferencesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithOne("ProfileImage") + .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithMany("ItemDisplayPreferences") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithMany("Permissions") + .HasForeignKey("Permission_Permissions_Guid"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithMany("Preferences") + .HasForeignKey("Preference_Preferences_Guid"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Jellyfin.Server.Implementations/Migrations/20200905220533_FixDisplayPreferencesIndex.cs b/Jellyfin.Server.Implementations/Migrations/20200905220533_FixDisplayPreferencesIndex.cs new file mode 100644 index 0000000000..33c5bb4ca1 --- /dev/null +++ b/Jellyfin.Server.Implementations/Migrations/20200905220533_FixDisplayPreferencesIndex.cs @@ -0,0 +1,51 @@ +#pragma warning disable CS1591 +#pragma warning disable SA1601 + +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Jellyfin.Server.Implementations.Migrations +{ + public partial class FixDisplayPreferencesIndex : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_DisplayPreferences_UserId", + schema: "jellyfin", + table: "DisplayPreferences"); + + migrationBuilder.CreateIndex( + name: "IX_DisplayPreferences_UserId", + schema: "jellyfin", + table: "DisplayPreferences", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_DisplayPreferences_UserId_Client", + schema: "jellyfin", + table: "DisplayPreferences", + columns: new[] { "UserId", "Client" }, + unique: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_DisplayPreferences_UserId", + schema: "jellyfin", + table: "DisplayPreferences"); + + migrationBuilder.DropIndex( + name: "IX_DisplayPreferences_UserId_Client", + schema: "jellyfin", + table: "DisplayPreferences"); + + migrationBuilder.CreateIndex( + name: "IX_DisplayPreferences_UserId", + schema: "jellyfin", + table: "DisplayPreferences", + column: "UserId", + unique: true); + } + } +} diff --git a/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs b/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs index a6e6a23249..ccfcf96b1f 100644 --- a/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs +++ b/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs @@ -15,7 +15,7 @@ namespace Jellyfin.Server.Implementations.Migrations #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("jellyfin") - .HasAnnotation("ProductVersion", "3.1.6"); + .HasAnnotation("ProductVersion", "3.1.7"); modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => { @@ -136,7 +136,9 @@ namespace Jellyfin.Server.Implementations.Migrations b.HasKey("Id"); - b.HasIndex("UserId") + b.HasIndex("UserId"); + + b.HasIndex("UserId", "Client") .IsUnique(); b.ToTable("DisplayPreferences"); -- cgit v1.2.3 From 46ae51bc9aaf4564cdb38b02d6b87b9cfcc82bfb Mon Sep 17 00:00:00 2001 From: crobibero Date: Sat, 12 Sep 2020 10:19:04 -0600 Subject: update to dotnet 3.1.8 --- Emby.Server.Implementations/Emby.Server.Implementations.csproj | 8 ++++---- Jellyfin.Api/Jellyfin.Api.csproj | 4 ++-- Jellyfin.Data/Jellyfin.Data.csproj | 4 ++-- .../Jellyfin.Server.Implementations.csproj | 4 ++-- Jellyfin.Server/Jellyfin.Server.csproj | 8 ++++---- MediaBrowser.Common/MediaBrowser.Common.csproj | 4 ++-- MediaBrowser.Controller/MediaBrowser.Controller.csproj | 4 ++-- MediaBrowser.Model/MediaBrowser.Model.csproj | 2 +- MediaBrowser.Providers/MediaBrowser.Providers.csproj | 6 +++--- deployment/Dockerfile.debian.amd64 | 2 +- deployment/Dockerfile.debian.arm64 | 2 +- deployment/Dockerfile.debian.armhf | 2 +- deployment/Dockerfile.linux.amd64 | 2 +- deployment/Dockerfile.macos | 2 +- deployment/Dockerfile.portable | 2 +- deployment/Dockerfile.ubuntu.amd64 | 2 +- deployment/Dockerfile.ubuntu.arm64 | 2 +- deployment/Dockerfile.ubuntu.armhf | 2 +- deployment/Dockerfile.windows.amd64 | 2 +- tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 4 ++-- 20 files changed, 34 insertions(+), 34 deletions(-) (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 0a348f0d00..c84c7b53df 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -32,10 +32,10 @@ - - - - + + + + diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index ca0542b036..c27dce8ddf 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -14,9 +14,9 @@ - + - + diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index 95343f91b5..6bb0d8ce27 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -41,8 +41,8 @@ - - + + diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index 30ed3e6af3..4e79dd8d6c 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -24,11 +24,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 0ac309a0b0..648172fbf7 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -41,10 +41,10 @@ - - - - + + + + diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 70dcc2397c..322740cca8 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -18,8 +18,8 @@ - - + + diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 9854ec520f..6544704065 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -14,8 +14,8 @@ - - + + diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index c0a75009ae..2646810907 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -34,7 +34,7 @@ - + diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 39f93c479b..51ca26361d 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -16,9 +16,9 @@ - - - + + + diff --git a/deployment/Dockerfile.debian.amd64 b/deployment/Dockerfile.debian.amd64 index 1ac5f76d6c..7202c58838 100644 --- a/deployment/Dockerfile.debian.amd64 +++ b/deployment/Dockerfile.debian.amd64 @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/4f9b8a64-5e09-456c-a087-527cfc8b4cd2/15e14ec06eab947432de139f172f7a98/dotnet-sdk-3.1.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/f01e3d97-c1c3-4635-bc77-0c893be36820/6ec6acabc22468c6cc68b61625b14a7d/dotnet-sdk-3.1.402-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.debian.arm64 b/deployment/Dockerfile.debian.arm64 index 68381e7bfd..e9f30213f4 100644 --- a/deployment/Dockerfile.debian.arm64 +++ b/deployment/Dockerfile.debian.arm64 @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/4f9b8a64-5e09-456c-a087-527cfc8b4cd2/15e14ec06eab947432de139f172f7a98/dotnet-sdk-3.1.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/f01e3d97-c1c3-4635-bc77-0c893be36820/6ec6acabc22468c6cc68b61625b14a7d/dotnet-sdk-3.1.402-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.debian.armhf b/deployment/Dockerfile.debian.armhf index ce1b100c1c..91a8a6e7a1 100644 --- a/deployment/Dockerfile.debian.armhf +++ b/deployment/Dockerfile.debian.armhf @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/4f9b8a64-5e09-456c-a087-527cfc8b4cd2/15e14ec06eab947432de139f172f7a98/dotnet-sdk-3.1.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/f01e3d97-c1c3-4635-bc77-0c893be36820/6ec6acabc22468c6cc68b61625b14a7d/dotnet-sdk-3.1.402-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.linux.amd64 b/deployment/Dockerfile.linux.amd64 index b4a3c1b76d..828d5c2cf9 100644 --- a/deployment/Dockerfile.linux.amd64 +++ b/deployment/Dockerfile.linux.amd64 @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/4f9b8a64-5e09-456c-a087-527cfc8b4cd2/15e14ec06eab947432de139f172f7a98/dotnet-sdk-3.1.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/f01e3d97-c1c3-4635-bc77-0c893be36820/6ec6acabc22468c6cc68b61625b14a7d/dotnet-sdk-3.1.402-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.macos b/deployment/Dockerfile.macos index 7912e018e5..0b2a0fe5fa 100644 --- a/deployment/Dockerfile.macos +++ b/deployment/Dockerfile.macos @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/4f9b8a64-5e09-456c-a087-527cfc8b4cd2/15e14ec06eab947432de139f172f7a98/dotnet-sdk-3.1.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/f01e3d97-c1c3-4635-bc77-0c893be36820/6ec6acabc22468c6cc68b61625b14a7d/dotnet-sdk-3.1.402-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.portable b/deployment/Dockerfile.portable index 949f1ef8f8..7d5de230fa 100644 --- a/deployment/Dockerfile.portable +++ b/deployment/Dockerfile.portable @@ -15,7 +15,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/4f9b8a64-5e09-456c-a087-527cfc8b4cd2/15e14ec06eab947432de139f172f7a98/dotnet-sdk-3.1.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/f01e3d97-c1c3-4635-bc77-0c893be36820/6ec6acabc22468c6cc68b61625b14a7d/dotnet-sdk-3.1.402-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.amd64 b/deployment/Dockerfile.ubuntu.amd64 index 9518d84936..9c63f43dfa 100644 --- a/deployment/Dockerfile.ubuntu.amd64 +++ b/deployment/Dockerfile.ubuntu.amd64 @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/4f9b8a64-5e09-456c-a087-527cfc8b4cd2/15e14ec06eab947432de139f172f7a98/dotnet-sdk-3.1.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/f01e3d97-c1c3-4635-bc77-0c893be36820/6ec6acabc22468c6cc68b61625b14a7d/dotnet-sdk-3.1.402-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.arm64 b/deployment/Dockerfile.ubuntu.arm64 index 0174f2f2a9..51612dd443 100644 --- a/deployment/Dockerfile.ubuntu.arm64 +++ b/deployment/Dockerfile.ubuntu.arm64 @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/4f9b8a64-5e09-456c-a087-527cfc8b4cd2/15e14ec06eab947432de139f172f7a98/dotnet-sdk-3.1.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/f01e3d97-c1c3-4635-bc77-0c893be36820/6ec6acabc22468c6cc68b61625b14a7d/dotnet-sdk-3.1.402-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.armhf b/deployment/Dockerfile.ubuntu.armhf index 0e02240c8f..4ed7f86872 100644 --- a/deployment/Dockerfile.ubuntu.armhf +++ b/deployment/Dockerfile.ubuntu.armhf @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/4f9b8a64-5e09-456c-a087-527cfc8b4cd2/15e14ec06eab947432de139f172f7a98/dotnet-sdk-3.1.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/f01e3d97-c1c3-4635-bc77-0c893be36820/6ec6acabc22468c6cc68b61625b14a7d/dotnet-sdk-3.1.402-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.windows.amd64 b/deployment/Dockerfile.windows.amd64 index d1f2f9e48b..5671cc598a 100644 --- a/deployment/Dockerfile.windows.amd64 +++ b/deployment/Dockerfile.windows.amd64 @@ -15,7 +15,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/4f9b8a64-5e09-456c-a087-527cfc8b4cd2/15e14ec06eab947432de139f172f7a98/dotnet-sdk-3.1.401-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/f01e3d97-c1c3-4635-bc77-0c893be36820/6ec6acabc22468c6cc68b61625b14a7d/dotnet-sdk-3.1.402-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index bcba3a2032..e3a7a54286 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -16,8 +16,8 @@ - - + + -- cgit v1.2.3 From 72534f9d667f2457cbe96ea870d140528e366ba2 Mon Sep 17 00:00:00 2001 From: Niels van Velzen Date: Fri, 25 Sep 2020 09:25:59 +0200 Subject: Use SessionMessageType for WebSocket messages --- Emby.Dlna/PlayTo/PlayToController.cs | 8 ++-- .../EntryPoints/LibraryChangedNotifier.cs | 7 +-- .../EntryPoints/RecordingNotifier.cs | 11 ++--- .../EntryPoints/UserDataChangeNotifier.cs | 2 +- .../HttpServer/WebSocketConnection.cs | 5 ++- .../Session/SessionManager.cs | 28 ++++++------ .../Session/SessionWebSocketListener.cs | 3 +- .../Session/WebSocketController.cs | 3 +- .../ActivityLogWebSocketListener.cs | 14 +++--- .../ScheduledTasksWebSocketListener.cs | 14 +++--- .../SessionInfoWebSocketListener.cs | 9 +++- .../Consumers/System/TaskCompletedNotifier.cs | 3 +- .../Updates/PluginInstallationCancelledNotifier.cs | 3 +- .../Updates/PluginInstallationFailedNotifier.cs | 3 +- .../Consumers/Updates/PluginInstalledNotifier.cs | 3 +- .../Consumers/Updates/PluginInstallingNotifier.cs | 3 +- .../Consumers/Updates/PluginUninstalledNotifier.cs | 3 +- .../Events/Consumers/Users/UserDeletedNotifier.cs | 3 +- .../Events/Consumers/Users/UserUpdatedNotifier.cs | 3 +- .../Net/BasePeriodicWebSocketListener.cs | 27 +++++++++--- .../Session/ISessionController.cs | 3 +- MediaBrowser.Controller/Session/ISessionManager.cs | 8 ++-- MediaBrowser.Model/Net/WebSocketMessage.cs | 3 +- MediaBrowser.Model/Session/SessionMessageType.cs | 50 ++++++++++++++++++++++ 24 files changed, 156 insertions(+), 63 deletions(-) create mode 100644 MediaBrowser.Model/Session/SessionMessageType.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs index 460ac2d8d1..d09a11930d 100644 --- a/Emby.Dlna/PlayTo/PlayToController.cs +++ b/Emby.Dlna/PlayTo/PlayToController.cs @@ -811,7 +811,7 @@ namespace Emby.Dlna.PlayTo } /// - public Task SendMessage(string name, Guid messageId, T data, CancellationToken cancellationToken) + public Task SendMessage(SessionMessageType name, Guid messageId, T data, CancellationToken cancellationToken) { if (_disposed) { @@ -823,17 +823,17 @@ namespace Emby.Dlna.PlayTo return Task.CompletedTask; } - if (string.Equals(name, "Play", StringComparison.OrdinalIgnoreCase)) + if (name == SessionMessageType.Play) { return SendPlayCommand(data as PlayRequest, cancellationToken); } - if (string.Equals(name, "PlayState", StringComparison.OrdinalIgnoreCase)) + if (name == SessionMessageType.PlayState) { return SendPlaystateCommand(data as PlaystateRequest, cancellationToken); } - if (string.Equals(name, "GeneralCommand", StringComparison.OrdinalIgnoreCase)) + if (name == SessionMessageType.GeneralCommand) { return SendGeneralCommand(data as GeneralCommand, cancellationToken); } diff --git a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs index c9d21d9638..ff64e217a0 100644 --- a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs @@ -16,6 +16,7 @@ using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Session; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.EntryPoints @@ -105,7 +106,7 @@ namespace Emby.Server.Implementations.EntryPoints try { - _sessionManager.SendMessageToAdminSessions("RefreshProgress", dict, CancellationToken.None); + _sessionManager.SendMessageToAdminSessions(SessionMessageType.RefreshProgress, dict, CancellationToken.None); } catch { @@ -123,7 +124,7 @@ namespace Emby.Server.Implementations.EntryPoints try { - _sessionManager.SendMessageToAdminSessions("RefreshProgress", collectionFolderDict, CancellationToken.None); + _sessionManager.SendMessageToAdminSessions(SessionMessageType.RefreshProgress, collectionFolderDict, CancellationToken.None); } catch { @@ -345,7 +346,7 @@ namespace Emby.Server.Implementations.EntryPoints try { - await _sessionManager.SendMessageToUserSessions(new List { userId }, "LibraryChanged", info, cancellationToken).ConfigureAwait(false); + await _sessionManager.SendMessageToUserSessions(new List { userId }, SessionMessageType.LibraryChanged, info, cancellationToken).ConfigureAwait(false); } catch (Exception ex) { diff --git a/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs b/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs index 44d2580d68..824bb85f44 100644 --- a/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs @@ -10,6 +10,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Session; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.EntryPoints @@ -46,25 +47,25 @@ namespace Emby.Server.Implementations.EntryPoints private async void OnLiveTvManagerSeriesTimerCreated(object sender, GenericEventArgs e) { - await SendMessage("SeriesTimerCreated", e.Argument).ConfigureAwait(false); + await SendMessage(SessionMessageType.SeriesTimerCreated, e.Argument).ConfigureAwait(false); } private async void OnLiveTvManagerTimerCreated(object sender, GenericEventArgs e) { - await SendMessage("TimerCreated", e.Argument).ConfigureAwait(false); + await SendMessage(SessionMessageType.TimerCreated, e.Argument).ConfigureAwait(false); } private async void OnLiveTvManagerSeriesTimerCancelled(object sender, GenericEventArgs e) { - await SendMessage("SeriesTimerCancelled", e.Argument).ConfigureAwait(false); + await SendMessage(SessionMessageType.SeriesTimerCancelled, e.Argument).ConfigureAwait(false); } private async void OnLiveTvManagerTimerCancelled(object sender, GenericEventArgs e) { - await SendMessage("TimerCancelled", e.Argument).ConfigureAwait(false); + await SendMessage(SessionMessageType.TimerCancelled, e.Argument).ConfigureAwait(false); } - private async Task SendMessage(string name, TimerEventInfo info) + private async Task SendMessage(SessionMessageType name, TimerEventInfo info) { var users = _userManager.Users.Where(i => i.HasPermission(PermissionKind.EnableLiveTvAccess)).Select(i => i.Id).ToList(); diff --git a/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs index 3618b88c5d..ff09cc81ed 100644 --- a/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs @@ -116,7 +116,7 @@ namespace Emby.Server.Implementations.EntryPoints private Task SendNotifications(Guid userId, List changedItems, CancellationToken cancellationToken) { - return _sessionManager.SendMessageToUserSessions(new List { userId }, "UserDataChanged", () => GetUserDataChangeInfo(userId, changedItems), cancellationToken); + return _sessionManager.SendMessageToUserSessions(new List { userId }, SessionMessageType.UserDataChanged, () => GetUserDataChangeInfo(userId, changedItems), cancellationToken); } private UserDataChangeInfo GetUserDataChangeInfo(Guid userId, List changedItems) diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs index 7eae4e7646..fed2addf80 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs @@ -11,6 +11,7 @@ using System.Threading.Tasks; using MediaBrowser.Common.Json; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Net; +using MediaBrowser.Model.Session; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; @@ -227,7 +228,7 @@ namespace Emby.Server.Implementations.HttpServer Connection = this }; - if (info.MessageType.Equals("KeepAlive", StringComparison.Ordinal)) + if (info.MessageType == SessionMessageType.KeepAlive) { await SendKeepAliveResponse().ConfigureAwait(false); } @@ -244,7 +245,7 @@ namespace Emby.Server.Implementations.HttpServer new WebSocketMessage { MessageId = Guid.NewGuid(), - MessageType = "KeepAlive" + MessageType = SessionMessageType.KeepAlive }, CancellationToken.None); } diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index e42d478533..df1b1e4525 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -1064,10 +1064,10 @@ namespace Emby.Server.Implementations.Session AssertCanControl(session, controllingSession); } - return SendMessageToSession(session, "GeneralCommand", command, cancellationToken); + return SendMessageToSession(session, SessionMessageType.GeneralCommand, command, cancellationToken); } - private static async Task SendMessageToSession(SessionInfo session, string name, T data, CancellationToken cancellationToken) + private static async Task SendMessageToSession(SessionInfo session, SessionMessageType name, T data, CancellationToken cancellationToken) { var controllers = session.SessionControllers; var messageId = Guid.NewGuid(); @@ -1078,7 +1078,7 @@ namespace Emby.Server.Implementations.Session } } - private static Task SendMessageToSessions(IEnumerable sessions, string name, T data, CancellationToken cancellationToken) + private static Task SendMessageToSessions(IEnumerable sessions, SessionMessageType name, T data, CancellationToken cancellationToken) { IEnumerable GetTasks() { @@ -1178,7 +1178,7 @@ namespace Emby.Server.Implementations.Session } } - await SendMessageToSession(session, "Play", command, cancellationToken).ConfigureAwait(false); + await SendMessageToSession(session, SessionMessageType.Play, command, cancellationToken).ConfigureAwait(false); } /// @@ -1186,7 +1186,7 @@ namespace Emby.Server.Implementations.Session { CheckDisposed(); var session = GetSessionToRemoteControl(sessionId); - await SendMessageToSession(session, "SyncPlayCommand", command, cancellationToken).ConfigureAwait(false); + await SendMessageToSession(session, SessionMessageType.SyncPlayCommand, command, cancellationToken).ConfigureAwait(false); } /// @@ -1194,7 +1194,7 @@ namespace Emby.Server.Implementations.Session { CheckDisposed(); var session = GetSessionToRemoteControl(sessionId); - await SendMessageToSession(session, "SyncPlayGroupUpdate", command, cancellationToken).ConfigureAwait(false); + await SendMessageToSession(session, SessionMessageType.SyncPlayGroupUpdate, command, cancellationToken).ConfigureAwait(false); } private IEnumerable TranslateItemForPlayback(Guid id, User user) @@ -1297,7 +1297,7 @@ namespace Emby.Server.Implementations.Session } } - return SendMessageToSession(session, "Playstate", command, cancellationToken); + return SendMessageToSession(session, SessionMessageType.PlayState, command, cancellationToken); } private static void AssertCanControl(SessionInfo session, SessionInfo controllingSession) @@ -1322,7 +1322,7 @@ namespace Emby.Server.Implementations.Session { CheckDisposed(); - return SendMessageToSessions(Sessions, "RestartRequired", string.Empty, cancellationToken); + return SendMessageToSessions(Sessions, SessionMessageType.RestartRequired, string.Empty, cancellationToken); } /// @@ -1334,7 +1334,7 @@ namespace Emby.Server.Implementations.Session { CheckDisposed(); - return SendMessageToSessions(Sessions, "ServerShuttingDown", string.Empty, cancellationToken); + return SendMessageToSessions(Sessions, SessionMessageType.ServerShuttingDown, string.Empty, cancellationToken); } /// @@ -1348,7 +1348,7 @@ namespace Emby.Server.Implementations.Session _logger.LogDebug("Beginning SendServerRestartNotification"); - return SendMessageToSessions(Sessions, "ServerRestarting", string.Empty, cancellationToken); + return SendMessageToSessions(Sessions, SessionMessageType.ServerRestarting, string.Empty, cancellationToken); } /// @@ -1866,7 +1866,7 @@ namespace Emby.Server.Implementations.Session } /// - public Task SendMessageToAdminSessions(string name, T data, CancellationToken cancellationToken) + public Task SendMessageToAdminSessions(SessionMessageType name, T data, CancellationToken cancellationToken) { CheckDisposed(); @@ -1879,7 +1879,7 @@ namespace Emby.Server.Implementations.Session } /// - public Task SendMessageToUserSessions(List userIds, string name, Func dataFn, CancellationToken cancellationToken) + public Task SendMessageToUserSessions(List userIds, SessionMessageType name, Func dataFn, CancellationToken cancellationToken) { CheckDisposed(); @@ -1894,7 +1894,7 @@ namespace Emby.Server.Implementations.Session } /// - public Task SendMessageToUserSessions(List userIds, string name, T data, CancellationToken cancellationToken) + public Task SendMessageToUserSessions(List userIds, SessionMessageType name, T data, CancellationToken cancellationToken) { CheckDisposed(); @@ -1903,7 +1903,7 @@ namespace Emby.Server.Implementations.Session } /// - public Task SendMessageToUserDeviceSessions(string deviceId, string name, T data, CancellationToken cancellationToken) + public Task SendMessageToUserDeviceSessions(string deviceId, SessionMessageType name, T data, CancellationToken cancellationToken) { CheckDisposed(); diff --git a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs index 15c2af220d..a5f8479537 100644 --- a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs +++ b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs @@ -8,6 +8,7 @@ using Jellyfin.Data.Events; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Net; +using MediaBrowser.Model.Session; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; @@ -316,7 +317,7 @@ namespace Emby.Server.Implementations.Session return webSocket.SendAsync( new WebSocketMessage { - MessageType = "ForceKeepAlive", + MessageType = SessionMessageType.ForceKeepAlive, Data = WebSocketLostTimeout }, CancellationToken.None); diff --git a/Emby.Server.Implementations/Session/WebSocketController.cs b/Emby.Server.Implementations/Session/WebSocketController.cs index 94604ca1e0..b986ffa1cd 100644 --- a/Emby.Server.Implementations/Session/WebSocketController.cs +++ b/Emby.Server.Implementations/Session/WebSocketController.cs @@ -11,6 +11,7 @@ using System.Threading.Tasks; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Net; +using MediaBrowser.Model.Session; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.Session @@ -65,7 +66,7 @@ namespace Emby.Server.Implementations.Session /// public Task SendMessage( - string name, + SessionMessageType name, Guid messageId, T data, CancellationToken cancellationToken) diff --git a/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs index 849b3b7095..77d55828d1 100644 --- a/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs +++ b/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Jellyfin.Data.Events; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Session; using Microsoft.Extensions.Logging; namespace Jellyfin.Api.WebSocketListeners @@ -29,11 +30,14 @@ namespace Jellyfin.Api.WebSocketListeners _activityManager.EntryCreated += OnEntryCreated; } - /// - /// Gets the name. - /// - /// The name. - protected override string Name => "ActivityLogEntry"; + /// + protected override SessionMessageType Type => SessionMessageType.ActivityLogEntry; + + /// + protected override SessionMessageType StartType => SessionMessageType.ActivityLogEntryStart; + + /// + protected override SessionMessageType StopType => SessionMessageType.ActivityLogEntryStop; /// /// Gets the data to send. diff --git a/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs index 8a966c1376..80314b9236 100644 --- a/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs +++ b/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading.Tasks; using Jellyfin.Data.Events; using MediaBrowser.Controller.Net; +using MediaBrowser.Model.Session; using MediaBrowser.Model.Tasks; using Microsoft.Extensions.Logging; @@ -33,11 +34,14 @@ namespace Jellyfin.Api.WebSocketListeners _taskManager.TaskCompleted += OnTaskCompleted; } - /// - /// Gets the name. - /// - /// The name. - protected override string Name => "ScheduledTasksInfo"; + /// + protected override SessionMessageType Type => SessionMessageType.ScheduledTasksInfo; + + /// + protected override SessionMessageType StartType => SessionMessageType.ScheduledTasksInfoStart; + + /// + protected override SessionMessageType StopType => SessionMessageType.ScheduledTasksInfoStop; /// /// Gets the data to send. diff --git a/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs index 1fb5dc412c..1cf43a0053 100644 --- a/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs +++ b/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Session; using Microsoft.Extensions.Logging; namespace Jellyfin.Api.WebSocketListeners @@ -34,7 +35,13 @@ namespace Jellyfin.Api.WebSocketListeners } /// - protected override string Name => "Sessions"; + protected override SessionMessageType Type => SessionMessageType.Sessions; + + /// + protected override SessionMessageType StartType => SessionMessageType.SessionsStart; + + /// + protected override SessionMessageType StopType => SessionMessageType.SessionsStop; /// /// Gets the data to send. diff --git a/Jellyfin.Server.Implementations/Events/Consumers/System/TaskCompletedNotifier.cs b/Jellyfin.Server.Implementations/Events/Consumers/System/TaskCompletedNotifier.cs index 80ed56cd8f..0993c6df7b 100644 --- a/Jellyfin.Server.Implementations/Events/Consumers/System/TaskCompletedNotifier.cs +++ b/Jellyfin.Server.Implementations/Events/Consumers/System/TaskCompletedNotifier.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using MediaBrowser.Controller.Events; using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Session; using MediaBrowser.Model.Tasks; namespace Jellyfin.Server.Implementations.Events.Consumers.System @@ -25,7 +26,7 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.System /// public async Task OnEvent(TaskCompletionEventArgs eventArgs) { - await _sessionManager.SendMessageToAdminSessions("ScheduledTaskEnded", eventArgs.Result, CancellationToken.None).ConfigureAwait(false); + await _sessionManager.SendMessageToAdminSessions(SessionMessageType.ScheduledTaskEnded, eventArgs.Result, CancellationToken.None).ConfigureAwait(false); } } } diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallationCancelledNotifier.cs b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallationCancelledNotifier.cs index 1c600683a9..1d790da6b2 100644 --- a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallationCancelledNotifier.cs +++ b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallationCancelledNotifier.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using MediaBrowser.Controller.Events; using MediaBrowser.Controller.Events.Updates; using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Session; namespace Jellyfin.Server.Implementations.Events.Consumers.Updates { @@ -25,7 +26,7 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Updates /// public async Task OnEvent(PluginInstallationCancelledEventArgs eventArgs) { - await _sessionManager.SendMessageToAdminSessions("PackageInstallationCancelled", eventArgs.Argument, CancellationToken.None).ConfigureAwait(false); + await _sessionManager.SendMessageToAdminSessions(SessionMessageType.PackageInstallationCancelled, eventArgs.Argument, CancellationToken.None).ConfigureAwait(false); } } } diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallationFailedNotifier.cs b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallationFailedNotifier.cs index ea0c878d42..a1faf18fc4 100644 --- a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallationFailedNotifier.cs +++ b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallationFailedNotifier.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using MediaBrowser.Common.Updates; using MediaBrowser.Controller.Events; using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Session; namespace Jellyfin.Server.Implementations.Events.Consumers.Updates { @@ -25,7 +26,7 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Updates /// public async Task OnEvent(InstallationFailedEventArgs eventArgs) { - await _sessionManager.SendMessageToAdminSessions("PackageInstallationFailed", eventArgs.InstallationInfo, CancellationToken.None).ConfigureAwait(false); + await _sessionManager.SendMessageToAdminSessions(SessionMessageType.PackageInstallationFailed, eventArgs.InstallationInfo, CancellationToken.None).ConfigureAwait(false); } } } diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstalledNotifier.cs b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstalledNotifier.cs index 3dda5a04c4..bd1a714045 100644 --- a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstalledNotifier.cs +++ b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstalledNotifier.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using MediaBrowser.Controller.Events; using MediaBrowser.Controller.Events.Updates; using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Session; namespace Jellyfin.Server.Implementations.Events.Consumers.Updates { @@ -25,7 +26,7 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Updates /// public async Task OnEvent(PluginInstalledEventArgs eventArgs) { - await _sessionManager.SendMessageToAdminSessions("PackageInstallationCompleted", eventArgs.Argument, CancellationToken.None).ConfigureAwait(false); + await _sessionManager.SendMessageToAdminSessions(SessionMessageType.PackageInstallationCompleted, eventArgs.Argument, CancellationToken.None).ConfigureAwait(false); } } } diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallingNotifier.cs b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallingNotifier.cs index f691d11a7d..b513ac64ae 100644 --- a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallingNotifier.cs +++ b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginInstallingNotifier.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using MediaBrowser.Controller.Events; using MediaBrowser.Controller.Events.Updates; using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Session; namespace Jellyfin.Server.Implementations.Events.Consumers.Updates { @@ -25,7 +26,7 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Updates /// public async Task OnEvent(PluginInstallingEventArgs eventArgs) { - await _sessionManager.SendMessageToAdminSessions("PackageInstalling", eventArgs.Argument, CancellationToken.None).ConfigureAwait(false); + await _sessionManager.SendMessageToAdminSessions(SessionMessageType.PackageInstalling, eventArgs.Argument, CancellationToken.None).ConfigureAwait(false); } } } diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUninstalledNotifier.cs b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUninstalledNotifier.cs index 709692f6bb..1fd7b9adfc 100644 --- a/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUninstalledNotifier.cs +++ b/Jellyfin.Server.Implementations/Events/Consumers/Updates/PluginUninstalledNotifier.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using MediaBrowser.Controller.Events; using MediaBrowser.Controller.Events.Updates; using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Session; namespace Jellyfin.Server.Implementations.Events.Consumers.Updates { @@ -25,7 +26,7 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Updates /// public async Task OnEvent(PluginUninstalledEventArgs eventArgs) { - await _sessionManager.SendMessageToAdminSessions("PluginUninstalled", eventArgs.Argument, CancellationToken.None).ConfigureAwait(false); + await _sessionManager.SendMessageToAdminSessions(SessionMessageType.PackageUninstalled, eventArgs.Argument, CancellationToken.None).ConfigureAwait(false); } } } diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Users/UserDeletedNotifier.cs b/Jellyfin.Server.Implementations/Events/Consumers/Users/UserDeletedNotifier.cs index 10367a939b..303e886210 100644 --- a/Jellyfin.Server.Implementations/Events/Consumers/Users/UserDeletedNotifier.cs +++ b/Jellyfin.Server.Implementations/Events/Consumers/Users/UserDeletedNotifier.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Jellyfin.Data.Events.Users; using MediaBrowser.Controller.Events; using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Session; namespace Jellyfin.Server.Implementations.Events.Consumers.Users { @@ -30,7 +31,7 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Users { await _sessionManager.SendMessageToUserSessions( new List { eventArgs.Argument.Id }, - "UserDeleted", + SessionMessageType.UserDeleted, eventArgs.Argument.Id.ToString("N", CultureInfo.InvariantCulture), CancellationToken.None).ConfigureAwait(false); } diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Users/UserUpdatedNotifier.cs b/Jellyfin.Server.Implementations/Events/Consumers/Users/UserUpdatedNotifier.cs index 6081dd044f..a14911b94a 100644 --- a/Jellyfin.Server.Implementations/Events/Consumers/Users/UserUpdatedNotifier.cs +++ b/Jellyfin.Server.Implementations/Events/Consumers/Users/UserUpdatedNotifier.cs @@ -6,6 +6,7 @@ using Jellyfin.Data.Events.Users; using MediaBrowser.Controller.Events; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Session; namespace Jellyfin.Server.Implementations.Events.Consumers.Users { @@ -33,7 +34,7 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Users { await _sessionManager.SendMessageToUserSessions( new List { e.Argument.Id }, - "UserUpdated", + SessionMessageType.UserUpdated, _userManager.GetUserDto(e.Argument), CancellationToken.None).ConfigureAwait(false); } diff --git a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs index 916dea58be..28227603b2 100644 --- a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs +++ b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs @@ -8,6 +8,7 @@ using System.Net.WebSockets; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Model.Net; +using MediaBrowser.Model.Session; using Microsoft.Extensions.Logging; namespace MediaBrowser.Controller.Net @@ -28,10 +29,22 @@ namespace MediaBrowser.Controller.Net new List>(); /// - /// Gets the name. + /// Gets the type used for the messages sent to the client. /// - /// The name. - protected abstract string Name { get; } + /// The type. + protected abstract SessionMessageType Type { get; } + + /// + /// Gets the message type received from the client to start sending messages. + /// + /// The type. + protected abstract SessionMessageType StartType { get; } + + /// + /// Gets the message type received from the client to stop sending messages. + /// + /// The type. + protected abstract SessionMessageType StopType { get; } /// /// Gets the data to send. @@ -66,12 +79,12 @@ namespace MediaBrowser.Controller.Net throw new ArgumentNullException(nameof(message)); } - if (string.Equals(message.MessageType, Name + "Start", StringComparison.OrdinalIgnoreCase)) + if (message.MessageType == StartType) { Start(message); } - if (string.Equals(message.MessageType, Name + "Stop", StringComparison.OrdinalIgnoreCase)) + if (message.MessageType == StopType) { Stop(message); } @@ -159,7 +172,7 @@ namespace MediaBrowser.Controller.Net new WebSocketMessage { MessageId = Guid.NewGuid(), - MessageType = Name, + MessageType = Type, Data = data }, cancellationToken).ConfigureAwait(false); @@ -176,7 +189,7 @@ namespace MediaBrowser.Controller.Net } catch (Exception ex) { - Logger.LogError(ex, "Error sending web socket message {Name}", Name); + Logger.LogError(ex, "Error sending web socket message {Name}", Type); DisposeConnection(tuple); } } diff --git a/MediaBrowser.Controller/Session/ISessionController.cs b/MediaBrowser.Controller/Session/ISessionController.cs index 22d6e2a04e..bc4ccd44ca 100644 --- a/MediaBrowser.Controller/Session/ISessionController.cs +++ b/MediaBrowser.Controller/Session/ISessionController.cs @@ -3,6 +3,7 @@ using System; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Model.Session; namespace MediaBrowser.Controller.Session { @@ -23,6 +24,6 @@ namespace MediaBrowser.Controller.Session /// /// Sends the message. /// - Task SendMessage(string name, Guid messageId, T data, CancellationToken cancellationToken); + Task SendMessage(SessionMessageType name, Guid messageId, T data, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index 228b2331dc..04c3004ee6 100644 --- a/MediaBrowser.Controller/Session/ISessionManager.cs +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -188,16 +188,16 @@ namespace MediaBrowser.Controller.Session /// The data. /// The cancellation token. /// Task. - Task SendMessageToAdminSessions(string name, T data, CancellationToken cancellationToken); + Task SendMessageToAdminSessions(SessionMessageType name, T data, CancellationToken cancellationToken); /// /// Sends the message to user sessions. /// /// /// Task. - Task SendMessageToUserSessions(List userIds, string name, T data, CancellationToken cancellationToken); + Task SendMessageToUserSessions(List userIds, SessionMessageType name, T data, CancellationToken cancellationToken); - Task SendMessageToUserSessions(List userIds, string name, Func dataFn, CancellationToken cancellationToken); + Task SendMessageToUserSessions(List userIds, SessionMessageType name, Func dataFn, CancellationToken cancellationToken); /// /// Sends the message to user device sessions. @@ -208,7 +208,7 @@ namespace MediaBrowser.Controller.Session /// The data. /// The cancellation token. /// Task. - Task SendMessageToUserDeviceSessions(string deviceId, string name, T data, CancellationToken cancellationToken); + Task SendMessageToUserDeviceSessions(string deviceId, SessionMessageType name, T data, CancellationToken cancellationToken); /// /// Sends the restart required message. diff --git a/MediaBrowser.Model/Net/WebSocketMessage.cs b/MediaBrowser.Model/Net/WebSocketMessage.cs index 660eebeda6..bffbbe612d 100644 --- a/MediaBrowser.Model/Net/WebSocketMessage.cs +++ b/MediaBrowser.Model/Net/WebSocketMessage.cs @@ -2,6 +2,7 @@ #pragma warning disable CS1591 using System; +using MediaBrowser.Model.Session; namespace MediaBrowser.Model.Net { @@ -15,7 +16,7 @@ namespace MediaBrowser.Model.Net /// Gets or sets the type of the message. /// /// The type of the message. - public string MessageType { get; set; } + public SessionMessageType MessageType { get; set; } public Guid MessageId { get; set; } diff --git a/MediaBrowser.Model/Session/SessionMessageType.cs b/MediaBrowser.Model/Session/SessionMessageType.cs new file mode 100644 index 0000000000..23c41026dc --- /dev/null +++ b/MediaBrowser.Model/Session/SessionMessageType.cs @@ -0,0 +1,50 @@ +#pragma warning disable CS1591 + +namespace MediaBrowser.Model.Session +{ + /// + /// The different kinds of messages that are used in the WebSocket api. + /// + public enum SessionMessageType + { + // Server -> Client + ForceKeepAlive, + GeneralCommand, + UserDataChanged, + Sessions, + Play, + SyncPlayCommand, + SyncPlayGroupUpdate, + PlayState, + RestartRequired, + ServerShuttingDown, + ServerRestarting, + LibraryChanged, + UserDeleted, + UserUpdated, + SeriesTimerCreated, + TimerCreated, + SeriesTimerCancelled, + TimerCancelled, + RefreshProgress, + ScheduledTaskEnded, + PackageInstallationCancelled, + PackageInstallationFailed, + PackageInstallationCompleted, + PackageInstalling, + PackageUninstalled, + ActivityLogEntry, + ScheduledTasksInfo, + + // Client -> Server + ActivityLogEntryStart, + ActivityLogEntryStop, + SessionsStart, + SessionsStop, + ScheduledTasksInfoStart, + ScheduledTasksInfoStop, + + // Shared + KeepAlive, + } +} -- cgit v1.2.3 From 211c9cd60850c6c33d1211cc5a7e35a94b19bab4 Mon Sep 17 00:00:00 2001 From: KonH Date: Sat, 3 Oct 2020 22:03:23 +0700 Subject: Remove unnecessary null checks in some places Related to https://github.com/jellyfin/jellyfin/issues/2149 --- Jellyfin.Api/Helpers/MediaInfoHelper.cs | 2 +- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 5 +---- Jellyfin.Server.Implementations/Users/UserManager.cs | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Api/Helpers/MediaInfoHelper.cs b/Jellyfin.Api/Helpers/MediaInfoHelper.cs index 1207fb5134..e78f63b256 100644 --- a/Jellyfin.Api/Helpers/MediaInfoHelper.cs +++ b/Jellyfin.Api/Helpers/MediaInfoHelper.cs @@ -554,7 +554,7 @@ namespace Jellyfin.Api.Helpers private long? GetMaxBitrate(long? clientMaxBitrate, User user, string ipAddress) { var maxBitrate = clientMaxBitrate; - var remoteClientMaxBitrate = user?.RemoteClientBitrateLimit ?? 0; + var remoteClientMaxBitrate = user.RemoteClientBitrateLimit ?? 0; if (remoteClientMaxBitrate <= 0) { diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 64d1227f7c..0db1fabffe 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -740,10 +740,7 @@ namespace Jellyfin.Api.Helpers /// The state. private void OnFfMpegProcessExited(Process process, TranscodingJobDto job, StreamState state) { - if (job != null) - { - job.HasExited = true; - } + job.HasExited = true; _logger.LogDebug("Disposing stream resources"); state.Dispose(); diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index 8f04baa089..dfd7ee99da 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -799,7 +799,7 @@ namespace Jellyfin.Server.Implementations.Users private IList GetPasswordResetProviders(User user) { - var passwordResetProviderId = user?.PasswordResetProviderId; + var passwordResetProviderId = user.PasswordResetProviderId; var providers = _passwordResetProviders.Where(i => i.IsEnabled).ToArray(); if (!string.IsNullOrEmpty(passwordResetProviderId)) -- cgit v1.2.3 From a839b015f948fb8dee665d37f6ecb3796675da8a Mon Sep 17 00:00:00 2001 From: cvium Date: Sat, 3 Oct 2020 21:24:04 +0200 Subject: Disable invalid auth provider --- Jellyfin.Server.Implementations/Users/InvalidAuthProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Users/InvalidAuthProvider.cs b/Jellyfin.Server.Implementations/Users/InvalidAuthProvider.cs index e38cd07f0e..5f32479e1d 100644 --- a/Jellyfin.Server.Implementations/Users/InvalidAuthProvider.cs +++ b/Jellyfin.Server.Implementations/Users/InvalidAuthProvider.cs @@ -15,7 +15,7 @@ namespace Jellyfin.Server.Implementations.Users public string Name => "InvalidOrMissingAuthenticationProvider"; /// - public bool IsEnabled => true; + public bool IsEnabled => false; /// public Task Authenticate(string username, string password) -- cgit v1.2.3 From 5a7dda337f4cdda0d0c61adef3d2b13772e708d0 Mon Sep 17 00:00:00 2001 From: "Joshua M. Boniface" Date: Sun, 4 Oct 2020 11:50:00 -0400 Subject: Add active session tracking Adds a flag for a maximum number of user sessions, as well as an authentication check to ensure that the user is not above this level. --- Emby.Server.Implementations/Session/SessionManager.cs | 13 +++++++++++++ Jellyfin.Data/Entities/User.cs | 5 +++++ Jellyfin.Server.Implementations/Users/UserManager.cs | 2 ++ MediaBrowser.Model/Users/UserPolicy.cs | 6 ++++++ 4 files changed, 26 insertions(+) (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index e42d478533..5903d395a2 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -1484,6 +1484,19 @@ namespace Emby.Server.Implementations.Session throw new SecurityException("User is not allowed access from this device."); } + var sessionsCount = Sessions.Where(i => string.Equals(i.UserId, user.Id)).ToList().Count; + int maxActiveSessions = user.MaxActiveSessions; + _logger.LogDebug("Current/Max sessions for user {User}: {Sessions}/{Max}", user.Username, sessionsCount, maxActiveSessions); + if (maxActiveSessions >= 0 && sessionsCount >= maxActiveSessions) + { + throw new SecurityException( + "User {User} is at their maximum number of sessions ({Sessions}/{Max}).", + user.Username, + sessionsCount, + maxActiveSessions + ) + } + var token = GetAuthorizationToken(user, request.DeviceId, request.App, request.AppVersion, request.DeviceName); var session = LogSessionActivity( diff --git a/Jellyfin.Data/Entities/User.cs b/Jellyfin.Data/Entities/User.cs index f7ab57a1b1..daa4de0b57 100644 --- a/Jellyfin.Data/Entities/User.cs +++ b/Jellyfin.Data/Entities/User.cs @@ -188,6 +188,11 @@ namespace Jellyfin.Data.Entities /// public int? LoginAttemptsBeforeLockout { get; set; } + /// + /// Gets or sets the maximum number of active sessions the user can have at once. + /// + public int? MaxActiveSessions { get; set; } + /// /// Gets or sets the subtitle mode. /// diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index 8f04baa089..43698efb75 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -379,6 +379,7 @@ namespace Jellyfin.Server.Implementations.Users PasswordResetProviderId = user.PasswordResetProviderId, InvalidLoginAttemptCount = user.InvalidLoginAttemptCount, LoginAttemptsBeforeLockout = user.LoginAttemptsBeforeLockout ?? -1, + MaxActiveSessions = user.MaxActiveSessions ?? -1, IsAdministrator = user.HasPermission(PermissionKind.IsAdministrator), IsHidden = user.HasPermission(PermissionKind.IsHidden), IsDisabled = user.HasPermission(PermissionKind.IsDisabled), @@ -701,6 +702,7 @@ namespace Jellyfin.Server.Implementations.Users user.PasswordResetProviderId = policy.PasswordResetProviderId; user.InvalidLoginAttemptCount = policy.InvalidLoginAttemptCount; user.LoginAttemptsBeforeLockout = maxLoginAttempts; + user.MaxActiveSessions = policy.MaxActiveSessions; user.SyncPlayAccess = policy.SyncPlayAccess; user.SetPermission(PermissionKind.IsAdministrator, policy.IsAdministrator); user.SetPermission(PermissionKind.IsHidden, policy.IsHidden); diff --git a/MediaBrowser.Model/Users/UserPolicy.cs b/MediaBrowser.Model/Users/UserPolicy.cs index a1f01f7e8e..53dcb6bbd8 100644 --- a/MediaBrowser.Model/Users/UserPolicy.cs +++ b/MediaBrowser.Model/Users/UserPolicy.cs @@ -92,6 +92,10 @@ namespace MediaBrowser.Model.Users public int LoginAttemptsBeforeLockout { get; set; } + public int ActiveSessionCount { get; set; } + + public int MaxActiveSessions { get; set; } + public bool EnablePublicSharing { get; set; } public Guid[] BlockedMediaFolders { get; set; } @@ -144,6 +148,8 @@ namespace MediaBrowser.Model.Users LoginAttemptsBeforeLockout = -1; + MaxActiveSessions = -1; + EnableAllChannels = true; EnabledChannels = Array.Empty(); -- cgit v1.2.3 From b9d79d7635aa39052244f356e699bc125c88bc34 Mon Sep 17 00:00:00 2001 From: "Joshua M. Boniface" Date: Sun, 4 Oct 2020 13:14:32 -0400 Subject: Add DB migration for new MaxActiveSessions field --- .../20201004171403_MaxActiveSessions.Designer.cs | 462 +++++++++++++++++++++ .../Migrations/20201004171403_MaxActiveSessions.cs | 24 ++ .../Migrations/JellyfinDbModelSnapshot.cs | 5 +- 3 files changed, 490 insertions(+), 1 deletion(-) create mode 100644 Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.Designer.cs create mode 100644 Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.Designer.cs b/Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.Designer.cs new file mode 100644 index 0000000000..65a25c16de --- /dev/null +++ b/Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.Designer.cs @@ -0,0 +1,462 @@ +// +using System; +using Jellyfin.Server.Implementations; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Jellyfin.Server.Implementations.Migrations +{ + [DbContext(typeof(JellyfinDb))] + [Migration("20201004171403_MaxActiveSessions")] + partial class MaxActiveSessions + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("jellyfin") + .HasAnnotation("ProductVersion", "3.1.8"); + + modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DayOfWeek") + .HasColumnType("INTEGER"); + + b.Property("EndHour") + .HasColumnType("REAL"); + + b.Property("StartHour") + .HasColumnType("REAL"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AccessSchedules"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateCreated") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("LogSeverity") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(512); + + b.Property("Overview") + .HasColumnType("TEXT") + .HasMaxLength(512); + + b.Property("RowVersion") + .IsConcurrencyToken() + .HasColumnType("INTEGER"); + + b.Property("ShortOverview") + .HasColumnType("TEXT") + .HasMaxLength(512); + + b.Property("Type") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("ActivityLogs"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChromecastVersion") + .HasColumnType("INTEGER"); + + b.Property("Client") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("DashboardTheme") + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("EnableNextVideoInfoOverlay") + .HasColumnType("INTEGER"); + + b.Property("IndexBy") + .HasColumnType("INTEGER"); + + b.Property("ScrollDirection") + .HasColumnType("INTEGER"); + + b.Property("ShowBackdrop") + .HasColumnType("INTEGER"); + + b.Property("ShowSidebar") + .HasColumnType("INTEGER"); + + b.Property("SkipBackwardLength") + .HasColumnType("INTEGER"); + + b.Property("SkipForwardLength") + .HasColumnType("INTEGER"); + + b.Property("TvHome") + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("UserId", "Client") + .IsUnique(); + + b.ToTable("DisplayPreferences"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DisplayPreferencesId") + .HasColumnType("INTEGER"); + + b.Property("Order") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("DisplayPreferencesId"); + + b.ToTable("HomeSection"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("LastModified") + .HasColumnType("TEXT"); + + b.Property("Path") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(512); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("ImageInfos"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Client") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("IndexBy") + .HasColumnType("INTEGER"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.Property("RememberIndexing") + .HasColumnType("INTEGER"); + + b.Property("RememberSorting") + .HasColumnType("INTEGER"); + + b.Property("SortBy") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(64); + + b.Property("SortOrder") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("ViewType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("ItemDisplayPreferences"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Kind") + .HasColumnType("INTEGER"); + + b.Property("Permission_Permissions_Guid") + .HasColumnType("TEXT"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("Permission_Permissions_Guid"); + + b.ToTable("Permissions"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Kind") + .HasColumnType("INTEGER"); + + b.Property("Preference_Preferences_Guid") + .HasColumnType("TEXT"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .HasColumnType("INTEGER"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(65535); + + b.HasKey("Id"); + + b.HasIndex("Preference_Preferences_Guid"); + + b.ToTable("Preferences"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("AudioLanguagePreference") + .HasColumnType("TEXT") + .HasMaxLength(255); + + b.Property("AuthenticationProviderId") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(255); + + b.Property("DisplayCollectionsView") + .HasColumnType("INTEGER"); + + b.Property("DisplayMissingEpisodes") + .HasColumnType("INTEGER"); + + b.Property("EasyPassword") + .HasColumnType("TEXT") + .HasMaxLength(65535); + + b.Property("EnableAutoLogin") + .HasColumnType("INTEGER"); + + b.Property("EnableLocalPassword") + .HasColumnType("INTEGER"); + + b.Property("EnableNextEpisodeAutoPlay") + .HasColumnType("INTEGER"); + + b.Property("EnableUserPreferenceAccess") + .HasColumnType("INTEGER"); + + b.Property("HidePlayedInLatest") + .HasColumnType("INTEGER"); + + b.Property("InternalId") + .HasColumnType("INTEGER"); + + b.Property("InvalidLoginAttemptCount") + .HasColumnType("INTEGER"); + + b.Property("LastActivityDate") + .HasColumnType("TEXT"); + + b.Property("LastLoginDate") + .HasColumnType("TEXT"); + + b.Property("LoginAttemptsBeforeLockout") + .HasColumnType("INTEGER"); + + b.Property("MaxActiveSessions") + .HasColumnType("INTEGER"); + + b.Property("MaxParentalAgeRating") + .HasColumnType("INTEGER"); + + b.Property("MustUpdatePassword") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT") + .HasMaxLength(65535); + + b.Property("PasswordResetProviderId") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(255); + + b.Property("PlayDefaultAudioTrack") + .HasColumnType("INTEGER"); + + b.Property("RememberAudioSelections") + .HasColumnType("INTEGER"); + + b.Property("RememberSubtitleSelections") + .HasColumnType("INTEGER"); + + b.Property("RemoteClientBitrateLimit") + .HasColumnType("INTEGER"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .HasColumnType("INTEGER"); + + b.Property("SubtitleLanguagePreference") + .HasColumnType("TEXT") + .HasMaxLength(255); + + b.Property("SubtitleMode") + .HasColumnType("INTEGER"); + + b.Property("SyncPlayAccess") + .HasColumnType("INTEGER"); + + b.Property("Username") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(255); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithMany("AccessSchedules") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithOne("DisplayPreferences") + .HasForeignKey("Jellyfin.Data.Entities.DisplayPreferences", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => + { + b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) + .WithMany("HomeSections") + .HasForeignKey("DisplayPreferencesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithOne("ProfileImage") + .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithMany("ItemDisplayPreferences") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithMany("Permissions") + .HasForeignKey("Permission_Permissions_Guid"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithMany("Preferences") + .HasForeignKey("Preference_Preferences_Guid"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.cs b/Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.cs new file mode 100644 index 0000000000..4ce6a7bd89 --- /dev/null +++ b/Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.cs @@ -0,0 +1,24 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Jellyfin.Server.Implementations.Migrations +{ + public partial class MaxActiveSessions : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "MaxActiveSessions", + schema: "jellyfin", + table: "Users", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "MaxActiveSessions", + schema: "jellyfin", + table: "Users"); + } + } +} diff --git a/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs b/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs index ccfcf96b1f..3c9e1aee4b 100644 --- a/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs +++ b/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs @@ -15,7 +15,7 @@ namespace Jellyfin.Server.Implementations.Migrations #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("jellyfin") - .HasAnnotation("ProductVersion", "3.1.7"); + .HasAnnotation("ProductVersion", "3.1.8"); modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => { @@ -344,6 +344,9 @@ namespace Jellyfin.Server.Implementations.Migrations b.Property("LoginAttemptsBeforeLockout") .HasColumnType("INTEGER"); + b.Property("MaxActiveSessions") + .HasColumnType("INTEGER"); + b.Property("MaxParentalAgeRating") .HasColumnType("INTEGER"); -- cgit v1.2.3 From cd328a0be3a8a3e20c51eb999f1b858d5263bab1 Mon Sep 17 00:00:00 2001 From: "Joshua M. Boniface" Date: Sun, 4 Oct 2020 13:34:53 -0400 Subject: Remove default set for MaxActiveSessions --- Jellyfin.Server.Implementations/Users/UserManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index 43698efb75..d8ec2a3cdf 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -379,7 +379,7 @@ namespace Jellyfin.Server.Implementations.Users PasswordResetProviderId = user.PasswordResetProviderId, InvalidLoginAttemptCount = user.InvalidLoginAttemptCount, LoginAttemptsBeforeLockout = user.LoginAttemptsBeforeLockout ?? -1, - MaxActiveSessions = user.MaxActiveSessions ?? -1, + MaxActiveSessions = user.MaxActiveSessions, IsAdministrator = user.HasPermission(PermissionKind.IsAdministrator), IsHidden = user.HasPermission(PermissionKind.IsHidden), IsDisabled = user.HasPermission(PermissionKind.IsDisabled), -- cgit v1.2.3 From 725acb528aab34df5cd5c6b6e552e5f5e54b7fea Mon Sep 17 00:00:00 2001 From: "Joshua M. Boniface" Date: Sun, 4 Oct 2020 13:43:20 -0400 Subject: Add pragma warning disabled to migrations --- .../Migrations/20201004171403_MaxActiveSessions.Designer.cs | 4 +++- .../Migrations/20201004171403_MaxActiveSessions.cs | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.Designer.cs b/Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.Designer.cs index 65a25c16de..9eac077bda 100644 --- a/Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.Designer.cs +++ b/Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.Designer.cs @@ -1,4 +1,6 @@ -// +#pragma warning disable CS1591 + +// using System; using Jellyfin.Server.Implementations; using Microsoft.EntityFrameworkCore; diff --git a/Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.cs b/Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.cs index 4ce6a7bd89..f6ed3c66cd 100644 --- a/Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.cs +++ b/Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.cs @@ -1,4 +1,7 @@ -using Microsoft.EntityFrameworkCore.Migrations; +#pragma warning disable CS1591 +#pragma warning disable SA1601 + +using Microsoft.EntityFrameworkCore.Migrations; namespace Jellyfin.Server.Implementations.Migrations { -- cgit v1.2.3 From 4d7e7d6331243bd339464bd6010569c6c308088b Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 3 Oct 2020 21:14:25 -0400 Subject: Rewrite activity log backend to use a query class. --- Jellyfin.Api/Controllers/ActivityLogController.cs | 20 ++++++------ Jellyfin.Data/Queries/ActivityLogQuery.cs | 30 ++++++++++++++++++ .../Activity/ActivityManager.cs | 37 ++++++++++------------ MediaBrowser.Model/Activity/IActivityManager.cs | 9 ++---- 4 files changed, 58 insertions(+), 38 deletions(-) create mode 100644 Jellyfin.Data/Queries/ActivityLogQuery.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Api/Controllers/ActivityLogController.cs b/Jellyfin.Api/Controllers/ActivityLogController.cs index a07cea9c0c..b429cebecb 100644 --- a/Jellyfin.Api/Controllers/ActivityLogController.cs +++ b/Jellyfin.Api/Controllers/ActivityLogController.cs @@ -1,7 +1,7 @@ using System; -using System.Linq; +using System.Threading.Tasks; using Jellyfin.Api.Constants; -using Jellyfin.Data.Entities; +using Jellyfin.Data.Queries; using MediaBrowser.Model.Activity; using MediaBrowser.Model.Querying; using Microsoft.AspNetCore.Authorization; @@ -39,19 +39,19 @@ namespace Jellyfin.Api.Controllers /// A containing the log entries. [HttpGet("Entries")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult> GetLogEntries( + public async Task>> GetLogEntries( [FromQuery] int? startIndex, [FromQuery] int? limit, [FromQuery] DateTime? minDate, [FromQuery] bool? hasUserId) { - var filterFunc = new Func, IQueryable>( - entries => entries.Where(entry => entry.DateCreated >= minDate - && (!hasUserId.HasValue || (hasUserId.Value - ? entry.UserId != Guid.Empty - : entry.UserId == Guid.Empty)))); - - return _activityManager.GetPagedResult(filterFunc, startIndex, limit); + return await _activityManager.GetPagedResultAsync(new ActivityLogQuery + { + StartIndex = startIndex, + Limit = limit, + MinDate = minDate, + HasUserId = hasUserId + }).ConfigureAwait(false); } } } diff --git a/Jellyfin.Data/Queries/ActivityLogQuery.cs b/Jellyfin.Data/Queries/ActivityLogQuery.cs new file mode 100644 index 0000000000..92919d3a51 --- /dev/null +++ b/Jellyfin.Data/Queries/ActivityLogQuery.cs @@ -0,0 +1,30 @@ +using System; + +namespace Jellyfin.Data.Queries +{ + /// + /// A class representing a query to the activity logs. + /// + public class ActivityLogQuery + { + /// + /// Gets or sets the index to start at. + /// + public int? StartIndex { get; set; } + + /// + /// Gets or sets the maximum number of items to include. + /// + public int? Limit { get; set; } + + /// + /// Gets or sets a value indicating whether to take entries with a user id. + /// + public bool? HasUserId { get; set; } + + /// + /// Gets or sets the minimum date to query for. + /// + public DateTime? MinDate { get; set; } + } +} diff --git a/Jellyfin.Server.Implementations/Activity/ActivityManager.cs b/Jellyfin.Server.Implementations/Activity/ActivityManager.cs index abdd290d45..695e2fbd84 100644 --- a/Jellyfin.Server.Implementations/Activity/ActivityManager.cs +++ b/Jellyfin.Server.Implementations/Activity/ActivityManager.cs @@ -3,8 +3,10 @@ using System.Linq; using System.Threading.Tasks; using Jellyfin.Data.Entities; using Jellyfin.Data.Events; +using Jellyfin.Data.Queries; using MediaBrowser.Model.Activity; using MediaBrowser.Model.Querying; +using Microsoft.EntityFrameworkCore; namespace Jellyfin.Server.Implementations.Activity { @@ -39,41 +41,34 @@ namespace Jellyfin.Server.Implementations.Activity } /// - public QueryResult GetPagedResult( - Func, IQueryable> func, - int? startIndex, - int? limit) + public async Task> GetPagedResultAsync(ActivityLogQuery query) { - using var dbContext = _provider.CreateContext(); + await using var dbContext = _provider.CreateContext(); - var query = func(dbContext.ActivityLogs.OrderByDescending(entry => entry.DateCreated)); + IQueryable entries = dbContext.ActivityLogs.OrderByDescending(entry => entry.DateCreated); - if (startIndex.HasValue) + if (query.MinDate.HasValue) { - query = query.Skip(startIndex.Value); + entries = entries.Where(entry => entry.DateCreated >= query.MinDate); } - if (limit.HasValue) + if (query.HasUserId.HasValue) { - query = query.Take(limit.Value); + entries = entries.Where(entry => entry.UserId != Guid.Empty == query.HasUserId.Value ); } - // This converts the objects from the new database model to the old for compatibility with the existing API. - var list = query.Select(ConvertToOldModel).ToList(); - return new QueryResult { - Items = list, - TotalRecordCount = func(dbContext.ActivityLogs).Count() + Items = await entries.Skip(query.StartIndex ?? 0) + .Take(query.Limit ?? 100) + .Select(ConvertToOldModel) + .AsQueryable() + .ToListAsync() + .ConfigureAwait(false), + TotalRecordCount = await entries.CountAsync().ConfigureAwait(false) }; } - /// - public QueryResult GetPagedResult(int? startIndex, int? limit) - { - return GetPagedResult(logs => logs, startIndex, limit); - } - private static ActivityLogEntry ConvertToOldModel(ActivityLog entry) { return new ActivityLogEntry diff --git a/MediaBrowser.Model/Activity/IActivityManager.cs b/MediaBrowser.Model/Activity/IActivityManager.cs index d5344494e8..3e4ea208ed 100644 --- a/MediaBrowser.Model/Activity/IActivityManager.cs +++ b/MediaBrowser.Model/Activity/IActivityManager.cs @@ -1,10 +1,10 @@ #pragma warning disable CS1591 using System; -using System.Linq; using System.Threading.Tasks; using Jellyfin.Data.Entities; using Jellyfin.Data.Events; +using Jellyfin.Data.Queries; using MediaBrowser.Model.Querying; namespace MediaBrowser.Model.Activity @@ -15,11 +15,6 @@ namespace MediaBrowser.Model.Activity Task CreateAsync(ActivityLog entry); - QueryResult GetPagedResult(int? startIndex, int? limit); - - QueryResult GetPagedResult( - Func, IQueryable> func, - int? startIndex, - int? limit); + Task> GetPagedResultAsync(ActivityLogQuery query); } } -- cgit v1.2.3 From f2763a71e06c087c940f267313e24fb15dc13d37 Mon Sep 17 00:00:00 2001 From: "Joshua M. Boniface" Date: Sun, 4 Oct 2020 20:31:24 -0400 Subject: Rename migrations to match others --- ...20201004171403_AddMaxActiveSessions.Designer.cs | 464 +++++++++++++++++++++ .../20201004171403_AddMaxActiveSessions.cs | 27 ++ .../20201004171403_MaxActiveSessions.Designer.cs | 464 --------------------- .../Migrations/20201004171403_MaxActiveSessions.cs | 27 -- 4 files changed, 491 insertions(+), 491 deletions(-) create mode 100644 Jellyfin.Server.Implementations/Migrations/20201004171403_AddMaxActiveSessions.Designer.cs create mode 100644 Jellyfin.Server.Implementations/Migrations/20201004171403_AddMaxActiveSessions.cs delete mode 100644 Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.Designer.cs delete mode 100644 Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Migrations/20201004171403_AddMaxActiveSessions.Designer.cs b/Jellyfin.Server.Implementations/Migrations/20201004171403_AddMaxActiveSessions.Designer.cs new file mode 100644 index 0000000000..e5c326a326 --- /dev/null +++ b/Jellyfin.Server.Implementations/Migrations/20201004171403_AddMaxActiveSessions.Designer.cs @@ -0,0 +1,464 @@ +#pragma warning disable CS1591 + +// +using System; +using Jellyfin.Server.Implementations; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Jellyfin.Server.Implementations.Migrations +{ + [DbContext(typeof(JellyfinDb))] + [Migration("20201004171403_AddMaxActiveSessions")] + partial class AddMaxActiveSessions + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("jellyfin") + .HasAnnotation("ProductVersion", "3.1.8"); + + modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DayOfWeek") + .HasColumnType("INTEGER"); + + b.Property("EndHour") + .HasColumnType("REAL"); + + b.Property("StartHour") + .HasColumnType("REAL"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AccessSchedules"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateCreated") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("LogSeverity") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(512); + + b.Property("Overview") + .HasColumnType("TEXT") + .HasMaxLength(512); + + b.Property("RowVersion") + .IsConcurrencyToken() + .HasColumnType("INTEGER"); + + b.Property("ShortOverview") + .HasColumnType("TEXT") + .HasMaxLength(512); + + b.Property("Type") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("ActivityLogs"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChromecastVersion") + .HasColumnType("INTEGER"); + + b.Property("Client") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("DashboardTheme") + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("EnableNextVideoInfoOverlay") + .HasColumnType("INTEGER"); + + b.Property("IndexBy") + .HasColumnType("INTEGER"); + + b.Property("ScrollDirection") + .HasColumnType("INTEGER"); + + b.Property("ShowBackdrop") + .HasColumnType("INTEGER"); + + b.Property("ShowSidebar") + .HasColumnType("INTEGER"); + + b.Property("SkipBackwardLength") + .HasColumnType("INTEGER"); + + b.Property("SkipForwardLength") + .HasColumnType("INTEGER"); + + b.Property("TvHome") + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("UserId", "Client") + .IsUnique(); + + b.ToTable("DisplayPreferences"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DisplayPreferencesId") + .HasColumnType("INTEGER"); + + b.Property("Order") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("DisplayPreferencesId"); + + b.ToTable("HomeSection"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("LastModified") + .HasColumnType("TEXT"); + + b.Property("Path") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(512); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("ImageInfos"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Client") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(32); + + b.Property("IndexBy") + .HasColumnType("INTEGER"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.Property("RememberIndexing") + .HasColumnType("INTEGER"); + + b.Property("RememberSorting") + .HasColumnType("INTEGER"); + + b.Property("SortBy") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(64); + + b.Property("SortOrder") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("ViewType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("ItemDisplayPreferences"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Kind") + .HasColumnType("INTEGER"); + + b.Property("Permission_Permissions_Guid") + .HasColumnType("TEXT"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("Permission_Permissions_Guid"); + + b.ToTable("Permissions"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Kind") + .HasColumnType("INTEGER"); + + b.Property("Preference_Preferences_Guid") + .HasColumnType("TEXT"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .HasColumnType("INTEGER"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(65535); + + b.HasKey("Id"); + + b.HasIndex("Preference_Preferences_Guid"); + + b.ToTable("Preferences"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("AudioLanguagePreference") + .HasColumnType("TEXT") + .HasMaxLength(255); + + b.Property("AuthenticationProviderId") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(255); + + b.Property("DisplayCollectionsView") + .HasColumnType("INTEGER"); + + b.Property("DisplayMissingEpisodes") + .HasColumnType("INTEGER"); + + b.Property("EasyPassword") + .HasColumnType("TEXT") + .HasMaxLength(65535); + + b.Property("EnableAutoLogin") + .HasColumnType("INTEGER"); + + b.Property("EnableLocalPassword") + .HasColumnType("INTEGER"); + + b.Property("EnableNextEpisodeAutoPlay") + .HasColumnType("INTEGER"); + + b.Property("EnableUserPreferenceAccess") + .HasColumnType("INTEGER"); + + b.Property("HidePlayedInLatest") + .HasColumnType("INTEGER"); + + b.Property("InternalId") + .HasColumnType("INTEGER"); + + b.Property("InvalidLoginAttemptCount") + .HasColumnType("INTEGER"); + + b.Property("LastActivityDate") + .HasColumnType("TEXT"); + + b.Property("LastLoginDate") + .HasColumnType("TEXT"); + + b.Property("LoginAttemptsBeforeLockout") + .HasColumnType("INTEGER"); + + b.Property("MaxActiveSessions") + .HasColumnType("INTEGER"); + + b.Property("MaxParentalAgeRating") + .HasColumnType("INTEGER"); + + b.Property("MustUpdatePassword") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT") + .HasMaxLength(65535); + + b.Property("PasswordResetProviderId") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(255); + + b.Property("PlayDefaultAudioTrack") + .HasColumnType("INTEGER"); + + b.Property("RememberAudioSelections") + .HasColumnType("INTEGER"); + + b.Property("RememberSubtitleSelections") + .HasColumnType("INTEGER"); + + b.Property("RemoteClientBitrateLimit") + .HasColumnType("INTEGER"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .HasColumnType("INTEGER"); + + b.Property("SubtitleLanguagePreference") + .HasColumnType("TEXT") + .HasMaxLength(255); + + b.Property("SubtitleMode") + .HasColumnType("INTEGER"); + + b.Property("SyncPlayAccess") + .HasColumnType("INTEGER"); + + b.Property("Username") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(255); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithMany("AccessSchedules") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithOne("DisplayPreferences") + .HasForeignKey("Jellyfin.Data.Entities.DisplayPreferences", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => + { + b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) + .WithMany("HomeSections") + .HasForeignKey("DisplayPreferencesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithOne("ProfileImage") + .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithMany("ItemDisplayPreferences") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithMany("Permissions") + .HasForeignKey("Permission_Permissions_Guid"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithMany("Preferences") + .HasForeignKey("Preference_Preferences_Guid"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Jellyfin.Server.Implementations/Migrations/20201004171403_AddMaxActiveSessions.cs b/Jellyfin.Server.Implementations/Migrations/20201004171403_AddMaxActiveSessions.cs new file mode 100644 index 0000000000..8fded7d0a1 --- /dev/null +++ b/Jellyfin.Server.Implementations/Migrations/20201004171403_AddMaxActiveSessions.cs @@ -0,0 +1,27 @@ +#pragma warning disable CS1591 +#pragma warning disable SA1601 + +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Jellyfin.Server.Implementations.Migrations +{ + public partial class AddMaxActiveSessions : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "MaxActiveSessions", + schema: "jellyfin", + table: "Users", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "MaxActiveSessions", + schema: "jellyfin", + table: "Users"); + } + } +} diff --git a/Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.Designer.cs b/Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.Designer.cs deleted file mode 100644 index 9eac077bda..0000000000 --- a/Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.Designer.cs +++ /dev/null @@ -1,464 +0,0 @@ -#pragma warning disable CS1591 - -// -using System; -using Jellyfin.Server.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDb))] - [Migration("20201004171403_MaxActiveSessions")] - partial class MaxActiveSessions - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("jellyfin") - .HasAnnotation("ProductVersion", "3.1.8"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("Overview") - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(32); - - b.Property("DashboardTheme") - .HasColumnType("TEXT") - .HasMaxLength(32); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasColumnType("TEXT") - .HasMaxLength(32); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.HasIndex("UserId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(32); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(64); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("Permission_Permissions_Guid"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(65535); - - b.HasKey("Id"); - - b.HasIndex("Preference_Preferences_Guid"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EasyPassword") - .HasColumnType("TEXT") - .HasMaxLength(65535); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasColumnType("TEXT") - .HasMaxLength(65535); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.HasKey("Id"); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("DisplayPreferences") - .HasForeignKey("Jellyfin.Data.Entities.DisplayPreferences", "UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("Permission_Permissions_Guid"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("Preference_Preferences_Guid"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.cs b/Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.cs deleted file mode 100644 index f6ed3c66cd..0000000000 --- a/Jellyfin.Server.Implementations/Migrations/20201004171403_MaxActiveSessions.cs +++ /dev/null @@ -1,27 +0,0 @@ -#pragma warning disable CS1591 -#pragma warning disable SA1601 - -using Microsoft.EntityFrameworkCore.Migrations; - -namespace Jellyfin.Server.Implementations.Migrations -{ - public partial class MaxActiveSessions : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "MaxActiveSessions", - schema: "jellyfin", - table: "Users", - nullable: true); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "MaxActiveSessions", - schema: "jellyfin", - table: "Users"); - } - } -} -- cgit v1.2.3 From 49c363751a5bb54ee52e7764f223cd6263200c7c Mon Sep 17 00:00:00 2001 From: "Joshua M. Boniface" Date: Mon, 5 Oct 2020 13:33:22 -0400 Subject: Make MaxActiveSessions not nullable Fixes a bad assumption with the previous migration. --- .../Migrations/20201004171403_AddMaxActiveSessions.cs | 2 +- Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Migrations/20201004171403_AddMaxActiveSessions.cs b/Jellyfin.Server.Implementations/Migrations/20201004171403_AddMaxActiveSessions.cs index 8fded7d0a1..e6bf4192b3 100644 --- a/Jellyfin.Server.Implementations/Migrations/20201004171403_AddMaxActiveSessions.cs +++ b/Jellyfin.Server.Implementations/Migrations/20201004171403_AddMaxActiveSessions.cs @@ -13,7 +13,7 @@ namespace Jellyfin.Server.Implementations.Migrations name: "MaxActiveSessions", schema: "jellyfin", table: "Users", - nullable: true); + nullable: false); } protected override void Down(MigrationBuilder migrationBuilder) diff --git a/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs b/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs index 3c9e1aee4b..16d62f4826 100644 --- a/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs +++ b/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs @@ -344,7 +344,7 @@ namespace Jellyfin.Server.Implementations.Migrations b.Property("LoginAttemptsBeforeLockout") .HasColumnType("INTEGER"); - b.Property("MaxActiveSessions") + b.Property("MaxActiveSessions") .HasColumnType("INTEGER"); b.Property("MaxParentalAgeRating") -- cgit v1.2.3 From b3249e849c68c3474e18f999fc085d41bff75adc Mon Sep 17 00:00:00 2001 From: "Joshua M. Boniface" Date: Mon, 5 Oct 2020 16:54:51 -0400 Subject: Add default value of 0 --- .../Migrations/20201004171403_AddMaxActiveSessions.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Migrations/20201004171403_AddMaxActiveSessions.cs b/Jellyfin.Server.Implementations/Migrations/20201004171403_AddMaxActiveSessions.cs index e6bf4192b3..10acb4defb 100644 --- a/Jellyfin.Server.Implementations/Migrations/20201004171403_AddMaxActiveSessions.cs +++ b/Jellyfin.Server.Implementations/Migrations/20201004171403_AddMaxActiveSessions.cs @@ -13,7 +13,8 @@ namespace Jellyfin.Server.Implementations.Migrations name: "MaxActiveSessions", schema: "jellyfin", table: "Users", - nullable: false); + nullable: false, + defaultValue: 0); } protected override void Down(MigrationBuilder migrationBuilder) -- cgit v1.2.3 From d4a492ef93f6b663fd4a4f7710613f06863f401f Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Mon, 5 Oct 2020 22:51:52 -0400 Subject: Fix activity log query. --- Jellyfin.Server.Implementations/Activity/ActivityManager.cs | 9 ++++++--- .../Jellyfin.Server.Implementations.csproj | 1 + .../Users/DisplayPreferencesManager.cs | 1 + Jellyfin.Server.Implementations/Users/UserManager.cs | 11 ++++++----- 4 files changed, 14 insertions(+), 8 deletions(-) (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Activity/ActivityManager.cs b/Jellyfin.Server.Implementations/Activity/ActivityManager.cs index 695e2fbd84..5926abfe0d 100644 --- a/Jellyfin.Server.Implementations/Activity/ActivityManager.cs +++ b/Jellyfin.Server.Implementations/Activity/ActivityManager.cs @@ -45,7 +45,9 @@ namespace Jellyfin.Server.Implementations.Activity { await using var dbContext = _provider.CreateContext(); - IQueryable entries = dbContext.ActivityLogs.OrderByDescending(entry => entry.DateCreated); + IQueryable entries = dbContext.ActivityLogs + .AsQueryable() + .OrderByDescending(entry => entry.DateCreated); if (query.MinDate.HasValue) { @@ -59,10 +61,11 @@ namespace Jellyfin.Server.Implementations.Activity return new QueryResult { - Items = await entries.Skip(query.StartIndex ?? 0) + Items = await entries + .Skip(query.StartIndex ?? 0) .Take(query.Limit ?? 100) + .AsAsyncEnumerable() .Select(ConvertToOldModel) - .AsQueryable() .ToListAsync() .ConfigureAwait(false), TotalRecordCount = await entries.CountAsync().ConfigureAwait(false) diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index 4e79dd8d6c..17ba092588 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -24,6 +24,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs b/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs index 46f1c618f2..76f9433854 100644 --- a/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs +++ b/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs @@ -61,6 +61,7 @@ namespace Jellyfin.Server.Implementations.Users public IList ListItemDisplayPreferences(Guid userId, string client) { return _dbContext.ItemDisplayPreferences + .AsQueryable() .Where(prefs => prefs.UserId == userId && prefs.ItemId != Guid.Empty && string.Equals(prefs.Client, client)) .ToList(); } diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index 8f04baa089..8f6a0496ab 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -108,6 +108,7 @@ namespace Jellyfin.Server.Implementations.Users { using var dbContext = _dbProvider.CreateContext(); return dbContext.Users + .AsQueryable() .Select(user => user.Id) .ToList(); } @@ -200,8 +201,8 @@ namespace Jellyfin.Server.Implementations.Users internal async Task CreateUserInternalAsync(string name, JellyfinDb dbContext) { // TODO: Remove after user item data is migrated. - var max = await dbContext.Users.AnyAsync().ConfigureAwait(false) - ? await dbContext.Users.Select(u => u.InternalId).MaxAsync().ConfigureAwait(false) + var max = await dbContext.Users.AsQueryable().AnyAsync().ConfigureAwait(false) + ? await dbContext.Users.AsQueryable().Select(u => u.InternalId).MaxAsync().ConfigureAwait(false) : 0; return new User( @@ -221,7 +222,7 @@ namespace Jellyfin.Server.Implementations.Users throw new ArgumentException("Usernames can contain unicode symbols, numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"); } - using var dbContext = _dbProvider.CreateContext(); + await using var dbContext = _dbProvider.CreateContext(); var newUser = await CreateUserInternalAsync(name, dbContext).ConfigureAwait(false); @@ -587,9 +588,9 @@ namespace Jellyfin.Server.Implementations.Users public async Task InitializeAsync() { // TODO: Refactor the startup wizard so that it doesn't require a user to already exist. - using var dbContext = _dbProvider.CreateContext(); + await using var dbContext = _dbProvider.CreateContext(); - if (await dbContext.Users.AnyAsync().ConfigureAwait(false)) + if (await dbContext.Users.AsQueryable().AnyAsync().ConfigureAwait(false)) { return; } -- cgit v1.2.3 From f998e521072ac5d3c0725cbe9fb544e005b15dfe Mon Sep 17 00:00:00 2001 From: crobibero Date: Tue, 13 Oct 2020 18:50:04 -0600 Subject: Update to dotnet 3.1.9 --- Emby.Server.Implementations/Emby.Server.Implementations.csproj | 8 ++++---- Jellyfin.Api/Jellyfin.Api.csproj | 4 ++-- Jellyfin.Data/Jellyfin.Data.csproj | 4 ++-- .../Jellyfin.Server.Implementations.csproj | 4 ++-- Jellyfin.Server/Jellyfin.Server.csproj | 8 ++++---- MediaBrowser.Common/MediaBrowser.Common.csproj | 4 ++-- MediaBrowser.Controller/MediaBrowser.Controller.csproj | 4 ++-- MediaBrowser.Model/MediaBrowser.Model.csproj | 2 +- MediaBrowser.Providers/MediaBrowser.Providers.csproj | 6 +++--- deployment/Dockerfile.debian.amd64 | 2 +- deployment/Dockerfile.debian.arm64 | 2 +- deployment/Dockerfile.debian.armhf | 2 +- deployment/Dockerfile.linux.amd64 | 2 +- deployment/Dockerfile.macos | 2 +- deployment/Dockerfile.portable | 2 +- deployment/Dockerfile.ubuntu.amd64 | 2 +- deployment/Dockerfile.ubuntu.arm64 | 2 +- deployment/Dockerfile.ubuntu.armhf | 2 +- deployment/Dockerfile.windows.amd64 | 2 +- tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 4 ++-- 20 files changed, 34 insertions(+), 34 deletions(-) (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 9ed3cca99c..c762aa0b84 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -32,10 +32,10 @@ - - - - + + + + diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 6a00db4b1a..da0852cebc 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -14,9 +14,9 @@ - + - + diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index 6bb0d8ce27..5038988f96 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -41,8 +41,8 @@ - - + + diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index 17ba092588..c52be3b8a9 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -25,11 +25,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 761a92f6db..7de34f4160 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -38,10 +38,10 @@ - - - - + + + + diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 322740cca8..e716a6610f 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -18,8 +18,8 @@ - - + + diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 6544704065..4374317d67 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -14,8 +14,8 @@ - - + + diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 2646810907..253ee7e795 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -34,7 +34,7 @@ - + diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 794490cc52..24400eae53 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -16,9 +16,9 @@ - - - + + + diff --git a/deployment/Dockerfile.debian.amd64 b/deployment/Dockerfile.debian.amd64 index 7202c58838..aaca8fe01e 100644 --- a/deployment/Dockerfile.debian.amd64 +++ b/deployment/Dockerfile.debian.amd64 @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/f01e3d97-c1c3-4635-bc77-0c893be36820/6ec6acabc22468c6cc68b61625b14a7d/dotnet-sdk-3.1.402-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/fdd9ecec-56b4-40f4-b762-d7efe24fc3cd/ffef51844c92afa6714528e10609a30f/dotnet-sdk-3.1.403-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.debian.arm64 b/deployment/Dockerfile.debian.arm64 index e9f30213f4..594da04ceb 100644 --- a/deployment/Dockerfile.debian.arm64 +++ b/deployment/Dockerfile.debian.arm64 @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/f01e3d97-c1c3-4635-bc77-0c893be36820/6ec6acabc22468c6cc68b61625b14a7d/dotnet-sdk-3.1.402-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/fdd9ecec-56b4-40f4-b762-d7efe24fc3cd/ffef51844c92afa6714528e10609a30f/dotnet-sdk-3.1.403-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.debian.armhf b/deployment/Dockerfile.debian.armhf index 91a8a6e7a1..3e6e2d0d70 100644 --- a/deployment/Dockerfile.debian.armhf +++ b/deployment/Dockerfile.debian.armhf @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/f01e3d97-c1c3-4635-bc77-0c893be36820/6ec6acabc22468c6cc68b61625b14a7d/dotnet-sdk-3.1.402-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/fdd9ecec-56b4-40f4-b762-d7efe24fc3cd/ffef51844c92afa6714528e10609a30f/dotnet-sdk-3.1.403-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.linux.amd64 b/deployment/Dockerfile.linux.amd64 index 828d5c2cf9..f98881ebfe 100644 --- a/deployment/Dockerfile.linux.amd64 +++ b/deployment/Dockerfile.linux.amd64 @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/f01e3d97-c1c3-4635-bc77-0c893be36820/6ec6acabc22468c6cc68b61625b14a7d/dotnet-sdk-3.1.402-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/fdd9ecec-56b4-40f4-b762-d7efe24fc3cd/ffef51844c92afa6714528e10609a30f/dotnet-sdk-3.1.403-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.macos b/deployment/Dockerfile.macos index 0b2a0fe5fa..ec9d2d8c77 100644 --- a/deployment/Dockerfile.macos +++ b/deployment/Dockerfile.macos @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/f01e3d97-c1c3-4635-bc77-0c893be36820/6ec6acabc22468c6cc68b61625b14a7d/dotnet-sdk-3.1.402-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/fdd9ecec-56b4-40f4-b762-d7efe24fc3cd/ffef51844c92afa6714528e10609a30f/dotnet-sdk-3.1.403-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.portable b/deployment/Dockerfile.portable index 7d5de230fa..3523f8aceb 100644 --- a/deployment/Dockerfile.portable +++ b/deployment/Dockerfile.portable @@ -15,7 +15,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/f01e3d97-c1c3-4635-bc77-0c893be36820/6ec6acabc22468c6cc68b61625b14a7d/dotnet-sdk-3.1.402-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/fdd9ecec-56b4-40f4-b762-d7efe24fc3cd/ffef51844c92afa6714528e10609a30f/dotnet-sdk-3.1.403-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.amd64 b/deployment/Dockerfile.ubuntu.amd64 index 9c63f43dfa..0a365e1aee 100644 --- a/deployment/Dockerfile.ubuntu.amd64 +++ b/deployment/Dockerfile.ubuntu.amd64 @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/f01e3d97-c1c3-4635-bc77-0c893be36820/6ec6acabc22468c6cc68b61625b14a7d/dotnet-sdk-3.1.402-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/fdd9ecec-56b4-40f4-b762-d7efe24fc3cd/ffef51844c92afa6714528e10609a30f/dotnet-sdk-3.1.403-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.arm64 b/deployment/Dockerfile.ubuntu.arm64 index 51612dd443..ab3ec9b9f8 100644 --- a/deployment/Dockerfile.ubuntu.arm64 +++ b/deployment/Dockerfile.ubuntu.arm64 @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/f01e3d97-c1c3-4635-bc77-0c893be36820/6ec6acabc22468c6cc68b61625b14a7d/dotnet-sdk-3.1.402-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/fdd9ecec-56b4-40f4-b762-d7efe24fc3cd/ffef51844c92afa6714528e10609a30f/dotnet-sdk-3.1.403-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.armhf b/deployment/Dockerfile.ubuntu.armhf index 4ed7f86872..fa41bdf48a 100644 --- a/deployment/Dockerfile.ubuntu.armhf +++ b/deployment/Dockerfile.ubuntu.armhf @@ -16,7 +16,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/f01e3d97-c1c3-4635-bc77-0c893be36820/6ec6acabc22468c6cc68b61625b14a7d/dotnet-sdk-3.1.402-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/fdd9ecec-56b4-40f4-b762-d7efe24fc3cd/ffef51844c92afa6714528e10609a30f/dotnet-sdk-3.1.403-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.windows.amd64 b/deployment/Dockerfile.windows.amd64 index 5671cc598a..7216b2363b 100644 --- a/deployment/Dockerfile.windows.amd64 +++ b/deployment/Dockerfile.windows.amd64 @@ -15,7 +15,7 @@ RUN apt-get update \ # Install dotnet repository # https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current -RUN wget https://download.visualstudio.microsoft.com/download/pr/f01e3d97-c1c3-4635-bc77-0c893be36820/6ec6acabc22468c6cc68b61625b14a7d/dotnet-sdk-3.1.402-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget https://download.visualstudio.microsoft.com/download/pr/fdd9ecec-56b4-40f4-b762-d7efe24fc3cd/ffef51844c92afa6714528e10609a30f/dotnet-sdk-3.1.403-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index 8a559b7b62..aae436fb73 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -16,8 +16,8 @@ - - + + -- cgit v1.2.3 From 15a7f88e083a78a4219cbd004e6041b49c490b05 Mon Sep 17 00:00:00 2001 From: crobibero Date: Wed, 14 Oct 2020 11:44:11 -0600 Subject: Automatically clean activity log database --- .../Localization/Core/en-US.json | 2 + .../ScheduledTasks/Tasks/CleanActivityLogTask.cs | 68 ++++++++++++++++++++++ .../Activity/ActivityManager.cs | 12 ++++ MediaBrowser.Model/Activity/IActivityManager.cs | 7 +++ 4 files changed, 89 insertions(+) create mode 100644 Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs (limited to 'Jellyfin.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/en-US.json b/Emby.Server.Implementations/Localization/Core/en-US.json index 92c54fb0e6..bc973c9737 100644 --- a/Emby.Server.Implementations/Localization/Core/en-US.json +++ b/Emby.Server.Implementations/Localization/Core/en-US.json @@ -95,6 +95,8 @@ "TasksLibraryCategory": "Library", "TasksApplicationCategory": "Application", "TasksChannelsCategory": "Internet Channels", + "TaskCleanActivityLog": "Clean Activity Log", + "TaskCleanActivityLogDescription": "Deletes activity log entries older then the configured age.", "TaskCleanCache": "Clean Cache Directory", "TaskCleanCacheDescription": "Deletes cache files no longer needed by the system.", "TaskRefreshChapterImages": "Extract Chapter Images", diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs new file mode 100644 index 0000000000..50bc091c83 --- /dev/null +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Model.Activity; +using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.Tasks; + +namespace Emby.Server.Implementations.ScheduledTasks.Tasks +{ + /// + /// Deletes old activity log entries. + /// + public class CleanActivityLogTask : IScheduledTask, IConfigurableScheduledTask + { + private readonly ILocalizationManager _localization; + private readonly IActivityManager _activityManager; + + /// + /// Initializes a new instance of the class. + /// + /// Instance of the interface. + /// Instance of the interface. + public CleanActivityLogTask( + ILocalizationManager localization, + IActivityManager activityManager) + { + _localization = localization; + _activityManager = activityManager; + } + + /// + public string Name => _localization.GetLocalizedString("TaskCleanActivityLog"); + + /// + public string Key => "CleanActivityLog"; + + /// + public string Description => _localization.GetLocalizedString("TaskCleanActivityLogDescription"); + + /// + public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory"); + + /// + public bool IsHidden => false; + + /// + public bool IsEnabled => true; + + /// + public bool IsLogged => true; + + /// + public Task Execute(CancellationToken cancellationToken, IProgress progress) + { + // TODO allow configure + var startDate = DateTime.UtcNow.AddDays(-30); + return _activityManager.CleanAsync(startDate); + } + + /// + public IEnumerable GetDefaultTriggers() + { + return Enumerable.Empty(); + } + } +} \ No newline at end of file diff --git a/Jellyfin.Server.Implementations/Activity/ActivityManager.cs b/Jellyfin.Server.Implementations/Activity/ActivityManager.cs index 5926abfe0d..7bde4f35be 100644 --- a/Jellyfin.Server.Implementations/Activity/ActivityManager.cs +++ b/Jellyfin.Server.Implementations/Activity/ActivityManager.cs @@ -72,6 +72,18 @@ namespace Jellyfin.Server.Implementations.Activity }; } + /// + public async Task CleanAsync(DateTime startDate) + { + await using var dbContext = _provider.CreateContext(); + var entries = dbContext.ActivityLogs + .AsQueryable() + .Where(entry => entry.DateCreated <= startDate); + + dbContext.RemoveRange(entries); + await dbContext.SaveChangesAsync().ConfigureAwait(false); + } + private static ActivityLogEntry ConvertToOldModel(ActivityLog entry) { return new ActivityLogEntry diff --git a/MediaBrowser.Model/Activity/IActivityManager.cs b/MediaBrowser.Model/Activity/IActivityManager.cs index 3e4ea208ed..28073fb8d7 100644 --- a/MediaBrowser.Model/Activity/IActivityManager.cs +++ b/MediaBrowser.Model/Activity/IActivityManager.cs @@ -16,5 +16,12 @@ namespace MediaBrowser.Model.Activity Task CreateAsync(ActivityLog entry); Task> GetPagedResultAsync(ActivityLogQuery query); + + /// + /// Remove all activity logs before the specified date. + /// + /// Activity log start date. + /// A representing the asynchronous operation. + Task CleanAsync(DateTime startDate); } } -- cgit v1.2.3 From aff8684d2e513d4c73e7919f464e2d34d6d63047 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Mon, 26 Oct 2020 20:31:10 -0400 Subject: Add caching to users --- .../Users/UserManager.cs | 86 ++++++++-------------- 1 file changed, 31 insertions(+), 55 deletions(-) (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index 437833aa38..c8b754514c 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -2,6 +2,7 @@ #pragma warning disable CA1307 using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -48,6 +49,8 @@ namespace Jellyfin.Server.Implementations.Users private readonly DefaultAuthenticationProvider _defaultAuthenticationProvider; private readonly DefaultPasswordResetProvider _defaultPasswordResetProvider; + private readonly IDictionary _users = new ConcurrentDictionary(); + /// /// Initializes a new instance of the class. /// @@ -81,6 +84,17 @@ namespace Jellyfin.Server.Implementations.Users _invalidAuthProvider = _authenticationProviders.OfType().First(); _defaultAuthenticationProvider = _authenticationProviders.OfType().First(); _defaultPasswordResetProvider = _passwordResetProviders.OfType().First(); + + using var dbContext = _dbProvider.CreateContext(); + foreach (var user in dbContext.Users + .Include(user => user.Permissions) + .Include(user => user.Preferences) + .Include(user => user.AccessSchedules) + .Include(user => user.ProfileImage) + .AsEnumerable()) + { + _users.Add(user.Id, user); + } } /// @@ -89,29 +103,13 @@ namespace Jellyfin.Server.Implementations.Users /// public IEnumerable Users { - get - { - using var dbContext = _dbProvider.CreateContext(); - return dbContext.Users - .Include(user => user.Permissions) - .Include(user => user.Preferences) - .Include(user => user.AccessSchedules) - .Include(user => user.ProfileImage) - .ToList(); - } + get { return _users.Values; } } /// public IEnumerable UsersIds { - get - { - using var dbContext = _dbProvider.CreateContext(); - return dbContext.Users - .AsQueryable() - .Select(user => user.Id) - .ToList(); - } + get { return _users.Keys; } } /// @@ -122,13 +120,8 @@ namespace Jellyfin.Server.Implementations.Users throw new ArgumentException("Guid can't be empty", nameof(id)); } - using var dbContext = _dbProvider.CreateContext(); - return dbContext.Users - .Include(user => user.Permissions) - .Include(user => user.Preferences) - .Include(user => user.AccessSchedules) - .Include(user => user.ProfileImage) - .FirstOrDefault(user => user.Id == id); + _users.TryGetValue(id, out var user); + return user; } /// @@ -139,14 +132,7 @@ namespace Jellyfin.Server.Implementations.Users throw new ArgumentException("Invalid username", nameof(name)); } - using var dbContext = _dbProvider.CreateContext(); - return dbContext.Users - .Include(user => user.Permissions) - .Include(user => user.Preferences) - .Include(user => user.AccessSchedules) - .Include(user => user.ProfileImage) - .AsEnumerable() - .FirstOrDefault(u => string.Equals(u.Username, name, StringComparison.OrdinalIgnoreCase)); + return _users.Values.FirstOrDefault(u => string.Equals(u.Username, name, StringComparison.OrdinalIgnoreCase)); } /// @@ -205,13 +191,17 @@ namespace Jellyfin.Server.Implementations.Users ? await dbContext.Users.AsQueryable().Select(u => u.InternalId).MaxAsync().ConfigureAwait(false) : 0; - return new User( + var user = new User( name, _defaultAuthenticationProvider.GetType().FullName, _defaultPasswordResetProvider.GetType().FullName) { InternalId = max + 1 }; + + _users.Add(user.Id, user); + + return user; } /// @@ -237,28 +227,12 @@ namespace Jellyfin.Server.Implementations.Users /// public void DeleteUser(Guid userId) { - using var dbContext = _dbProvider.CreateContext(); - var user = dbContext.Users - .Include(u => u.Permissions) - .Include(u => u.Preferences) - .Include(u => u.AccessSchedules) - .Include(u => u.ProfileImage) - .FirstOrDefault(u => u.Id == userId); - if (user == null) + if (!_users.TryGetValue(userId, out var user)) { throw new ResourceNotFoundException(nameof(userId)); } - if (dbContext.Users.Find(user.Id) == null) - { - throw new ArgumentException(string.Format( - CultureInfo.InvariantCulture, - "The user cannot be deleted because there is no user with the Name {0} and Id {1}.", - user.Username, - user.Id)); - } - - if (dbContext.Users.Count() == 1) + if (_users.Count == 1) { throw new InvalidOperationException(string.Format( CultureInfo.InvariantCulture, @@ -277,6 +251,8 @@ namespace Jellyfin.Server.Implementations.Users nameof(userId)); } + using var dbContext = _dbProvider.CreateContext(); + // Clear all entities related to the user from the database. if (user.ProfileImage != null) { @@ -288,6 +264,7 @@ namespace Jellyfin.Server.Implementations.Users dbContext.RemoveRange(user.AccessSchedules); dbContext.Users.Remove(user); dbContext.SaveChanges(); + _users.Remove(userId); _eventManager.Publish(new UserDeletedEventArgs(user)); } @@ -589,9 +566,7 @@ namespace Jellyfin.Server.Implementations.Users public async Task InitializeAsync() { // TODO: Refactor the startup wizard so that it doesn't require a user to already exist. - await using var dbContext = _dbProvider.CreateContext(); - - if (await dbContext.Users.AsQueryable().AnyAsync().ConfigureAwait(false)) + if (_users.Any()) { return; } @@ -604,6 +579,7 @@ namespace Jellyfin.Server.Implementations.Users _logger.LogWarning("No users, creating one with username {UserName}", defaultName); + await using var dbContext = _dbProvider.CreateContext(); var newUser = await CreateUserInternalAsync(defaultName, dbContext).ConfigureAwait(false); newUser.SetPermission(PermissionKind.IsAdministrator, true); newUser.SetPermission(PermissionKind.EnableContentDeletion, true); -- cgit v1.2.3 From f051590f14d38012bd8885c6e5ed0406d3c91ecc Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Tue, 27 Oct 2020 12:12:08 -0400 Subject: Apply suggestions --- Jellyfin.Server.Implementations/Users/UserManager.cs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index c8b754514c..efc3f439d8 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -49,7 +49,7 @@ namespace Jellyfin.Server.Implementations.Users private readonly DefaultAuthenticationProvider _defaultAuthenticationProvider; private readonly DefaultPasswordResetProvider _defaultPasswordResetProvider; - private readonly IDictionary _users = new ConcurrentDictionary(); + private readonly IDictionary _users; /// /// Initializes a new instance of the class. @@ -85,6 +85,7 @@ namespace Jellyfin.Server.Implementations.Users _defaultAuthenticationProvider = _authenticationProviders.OfType().First(); _defaultPasswordResetProvider = _passwordResetProviders.OfType().First(); + _users = new ConcurrentDictionary(); using var dbContext = _dbProvider.CreateContext(); foreach (var user in dbContext.Users .Include(user => user.Permissions) @@ -101,16 +102,10 @@ namespace Jellyfin.Server.Implementations.Users public event EventHandler>? OnUserUpdated; /// - public IEnumerable Users - { - get { return _users.Values; } - } + public IEnumerable Users => _users.Values; /// - public IEnumerable UsersIds - { - get { return _users.Keys; } - } + public IEnumerable UsersIds => _users.Keys; /// public User? GetUserById(Guid id) -- cgit v1.2.3 From 67f39ed54fe4182783efcbbee6338455ceecf30b Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Tue, 27 Oct 2020 12:28:37 -0400 Subject: Properly remove profile images --- Jellyfin.Server.Implementations/Users/UserManager.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index efc3f439d8..b39333b5cd 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -724,6 +724,7 @@ namespace Jellyfin.Server.Implementations.Users using var dbContext = _dbProvider.CreateContext(); dbContext.Remove(user.ProfileImage); dbContext.SaveChanges(); + user.ProfileImage = null; } private static bool IsValidUsername(string name) -- cgit v1.2.3 From d887e424052e3f57b7578d9dc7f62bcd8085fcbe Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Thu, 29 Oct 2020 19:16:39 -0400 Subject: Fix possible NullReferenceException --- Jellyfin.Server.Implementations/Users/UserManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index 437833aa38..5f25c7737a 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -460,7 +460,7 @@ namespace Jellyfin.Server.Implementations.Users // the authentication provider might have created it user = Users.FirstOrDefault(i => string.Equals(username, i.Username, StringComparison.OrdinalIgnoreCase)); - if (authenticationProvider is IHasNewUserPolicy hasNewUserPolicy) + if (authenticationProvider is IHasNewUserPolicy hasNewUserPolicy && user != null) { UpdatePolicy(user.Id, hasNewUserPolicy.GetNewUserPolicy()); -- cgit v1.2.3 From 72263613d039ccfb70b70bae9f53da53bc8757c4 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Thu, 29 Oct 2020 20:30:33 -0400 Subject: Convert some code in UserManager to async --- Jellyfin.Api/Controllers/ImageController.cs | 6 +++--- Jellyfin.Api/Controllers/UserController.cs | 18 +++++++----------- .../Users/UserManager.cs | 22 ++++++++++------------ MediaBrowser.Controller/Library/IUserManager.cs | 9 ++++++--- 4 files changed, 26 insertions(+), 29 deletions(-) (limited to 'Jellyfin.Server.Implementations') diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index 05efe23553..4a67c1aede 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -109,7 +109,7 @@ namespace Jellyfin.Api.Controllers var userDataPath = Path.Combine(_serverConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, user.Username); if (user.ProfileImage != null) { - _userManager.ClearProfileImage(user); + await _userManager.ClearProfileImageAsync(user).ConfigureAwait(false); } user.ProfileImage = new Data.Entities.ImageInfo(Path.Combine(userDataPath, "profile" + MimeTypes.ToExtension(mimeType))); @@ -138,7 +138,7 @@ namespace Jellyfin.Api.Controllers [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status403Forbidden)] - public ActionResult DeleteUserImage( + public async Task DeleteUserImage( [FromRoute, Required] Guid userId, [FromRoute, Required] ImageType imageType, [FromRoute] int? index = null) @@ -158,7 +158,7 @@ namespace Jellyfin.Api.Controllers _logger.LogError(e, "Error deleting user profile image:"); } - _userManager.ClearProfileImage(user); + await _userManager.ClearProfileImageAsync(user).ConfigureAwait(false); return NoContent(); } diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs index 50bb8bb2aa..7b0897bfb9 100644 --- a/Jellyfin.Api/Controllers/UserController.cs +++ b/Jellyfin.Api/Controllers/UserController.cs @@ -381,17 +381,13 @@ namespace Jellyfin.Api.Controllers var user = _userManager.GetUserById(userId); - if (string.Equals(user.Username, updateUser.Name, StringComparison.Ordinal)) - { - await _userManager.UpdateUserAsync(user).ConfigureAwait(false); - _userManager.UpdateConfiguration(user.Id, updateUser.Configuration); - } - else + if (!string.Equals(user.Username, updateUser.Name, StringComparison.Ordinal)) { await _userManager.RenameUser(user, updateUser.Name).ConfigureAwait(false); - _userManager.UpdateConfiguration(updateUser.Id, updateUser.Configuration); } + await _userManager.UpdateConfigurationAsync(user.Id, updateUser.Configuration).ConfigureAwait(false); + return NoContent(); } @@ -409,7 +405,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status403Forbidden)] - public ActionResult UpdateUserPolicy( + public async Task UpdateUserPolicy( [FromRoute, Required] Guid userId, [FromBody] UserPolicy newPolicy) { @@ -447,7 +443,7 @@ namespace Jellyfin.Api.Controllers _sessionManager.RevokeUserTokens(user.Id, currentToken); } - _userManager.UpdatePolicy(userId, newPolicy); + await _userManager.UpdatePolicyAsync(userId, newPolicy).ConfigureAwait(false); return NoContent(); } @@ -464,7 +460,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status403Forbidden)] - public ActionResult UpdateUserConfiguration( + public async Task UpdateUserConfiguration( [FromRoute, Required] Guid userId, [FromBody] UserConfiguration userConfig) { @@ -473,7 +469,7 @@ namespace Jellyfin.Api.Controllers return Forbid("User configuration update not allowed"); } - _userManager.UpdateConfiguration(userId, userConfig); + await _userManager.UpdateConfigurationAsync(userId, userConfig).ConfigureAwait(false); return NoContent(); } diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index b41a5ee5ca..40b89ed284 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -434,9 +434,7 @@ namespace Jellyfin.Server.Implementations.Users if (authenticationProvider is IHasNewUserPolicy hasNewUserPolicy && user != null) { - UpdatePolicy(user.Id, hasNewUserPolicy.GetNewUserPolicy()); - - await UpdateUserAsync(user).ConfigureAwait(false); + await UpdatePolicyAsync(user.Id, hasNewUserPolicy.GetNewUserPolicy()).ConfigureAwait(false); } } } @@ -615,9 +613,9 @@ namespace Jellyfin.Server.Implementations.Users } /// - public void UpdateConfiguration(Guid userId, UserConfiguration config) + public async Task UpdateConfigurationAsync(Guid userId, UserConfiguration config) { - using var dbContext = _dbProvider.CreateContext(); + await using var dbContext = _dbProvider.CreateContext(); var user = dbContext.Users .Include(u => u.Permissions) .Include(u => u.Preferences) @@ -644,13 +642,13 @@ namespace Jellyfin.Server.Implementations.Users user.SetPreference(PreferenceKind.LatestItemExcludes, config.LatestItemsExcludes); dbContext.Update(user); - dbContext.SaveChanges(); + await dbContext.SaveChangesAsync().ConfigureAwait(false); } /// - public void UpdatePolicy(Guid userId, UserPolicy policy) + public async Task UpdatePolicyAsync(Guid userId, UserPolicy policy) { - using var dbContext = _dbProvider.CreateContext(); + await using var dbContext = _dbProvider.CreateContext(); var user = dbContext.Users .Include(u => u.Permissions) .Include(u => u.Preferences) @@ -715,15 +713,15 @@ namespace Jellyfin.Server.Implementations.Users user.SetPreference(PreferenceKind.EnableContentDeletionFromFolders, policy.EnableContentDeletionFromFolders); dbContext.Update(user); - dbContext.SaveChanges(); + await dbContext.SaveChangesAsync().ConfigureAwait(false); } /// - public void ClearProfileImage(User user) + public async Task ClearProfileImageAsync(User user) { - using var dbContext = _dbProvider.CreateContext(); + await using var dbContext = _dbProvider.CreateContext(); dbContext.Remove(user.ProfileImage); - dbContext.SaveChanges(); + await dbContext.SaveChangesAsync().ConfigureAwait(false); user.ProfileImage = null; } diff --git a/MediaBrowser.Controller/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs index 6a4f5cf679..8fd3b8c347 100644 --- a/MediaBrowser.Controller/Library/IUserManager.cs +++ b/MediaBrowser.Controller/Library/IUserManager.cs @@ -158,7 +158,8 @@ namespace MediaBrowser.Controller.Library /// /// The user's Id. /// The request containing the new user configuration. - void UpdateConfiguration(Guid userId, UserConfiguration config); + /// A task representing the update. + Task UpdateConfigurationAsync(Guid userId, UserConfiguration config); /// /// This method updates the user's policy. @@ -167,12 +168,14 @@ namespace MediaBrowser.Controller.Library /// /// The user's Id. /// The request containing the new user policy. - void UpdatePolicy(Guid userId, UserPolicy policy); + /// A task representing the update. + Task UpdatePolicyAsync(Guid userId, UserPolicy policy); /// /// Clears the user's profile image. /// /// The user. - void ClearProfileImage(User user); + /// A task representing the clearing of the profile image. + Task ClearProfileImageAsync(User user); } } -- cgit v1.2.3