Merge pull request #23 from jellyfin/master

updating
This commit is contained in:
BaronGreenback 2020-06-15 10:01:55 +01:00 committed by GitHub
commit 862bcdba67
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
335 changed files with 4355 additions and 3477 deletions

View File

@ -7,6 +7,7 @@
- [anthonylavado](https://github.com/anthonylavado) - [anthonylavado](https://github.com/anthonylavado)
- [Artiume](https://github.com/Artiume) - [Artiume](https://github.com/Artiume)
- [AThomsen](https://github.com/AThomsen) - [AThomsen](https://github.com/AThomsen)
- [barronpm](https://github.com/barronpm)
- [bilde2910](https://github.com/bilde2910) - [bilde2910](https://github.com/bilde2910)
- [bfayers](https://github.com/bfayers) - [bfayers](https://github.com/bfayers)
- [BnMcG](https://github.com/BnMcG) - [BnMcG](https://github.com/BnMcG)
@ -130,6 +131,7 @@
- [XVicarious](https://github.com/XVicarious) - [XVicarious](https://github.com/XVicarious)
- [YouKnowBlom](https://github.com/YouKnowBlom) - [YouKnowBlom](https://github.com/YouKnowBlom)
- [KristupasSavickas](https://github.com/KristupasSavickas) - [KristupasSavickas](https://github.com/KristupasSavickas)
- [Pusta](https://github.com/pusta)
# Emby Contributors # Emby Contributors

View File

@ -4,11 +4,12 @@ using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Emby.Dlna.Service; using Emby.Dlna.Service;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common.Net; using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.TV; using MediaBrowser.Controller.TV;
@ -32,7 +33,8 @@ namespace Emby.Dlna.ContentDirectory
private readonly IMediaEncoder _mediaEncoder; private readonly IMediaEncoder _mediaEncoder;
private readonly ITVSeriesManager _tvSeriesManager; private readonly ITVSeriesManager _tvSeriesManager;
public ContentDirectory(IDlnaManager dlna, public ContentDirectory(
IDlnaManager dlna,
IUserDataManager userDataManager, IUserDataManager userDataManager,
IImageProcessor imageProcessor, IImageProcessor imageProcessor,
ILibraryManager libraryManager, ILibraryManager libraryManager,
@ -131,7 +133,7 @@ namespace Emby.Dlna.ContentDirectory
foreach (var user in _userManager.Users) foreach (var user in _userManager.Users)
{ {
if (user.Policy.IsAdministrator) if (user.HasPermission(PermissionKind.IsAdministrator))
{ {
return user; return user;
} }

View File

@ -10,6 +10,7 @@ using System.Threading;
using System.Xml; using System.Xml;
using Emby.Dlna.Didl; using Emby.Dlna.Didl;
using Emby.Dlna.Service; using Emby.Dlna.Service;
using Jellyfin.Data.Entities;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Drawing;
@ -17,7 +18,6 @@ using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
@ -28,6 +28,12 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Book = MediaBrowser.Controller.Entities.Book;
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
using Genre = MediaBrowser.Controller.Entities.Genre;
using Movie = MediaBrowser.Controller.Entities.Movies.Movie;
using MusicAlbum = MediaBrowser.Controller.Entities.Audio.MusicAlbum;
using Series = MediaBrowser.Controller.Entities.TV.Series;
namespace Emby.Dlna.ContentDirectory namespace Emby.Dlna.ContentDirectory
{ {
@ -731,7 +737,7 @@ namespace Emby.Dlna.ContentDirectory
return GetGenres(item, user, query); return GetGenres(item, user, query);
} }
var array = new ServerItem[] var array = new[]
{ {
new ServerItem(item) new ServerItem(item)
{ {
@ -1115,7 +1121,7 @@ namespace Emby.Dlna.ContentDirectory
private QueryResult<ServerItem> GetMusicPlaylists(User user, InternalItemsQuery query) private QueryResult<ServerItem> GetMusicPlaylists(User user, InternalItemsQuery query)
{ {
query.Parent = null; query.Parent = null;
query.IncludeItemTypes = new[] { typeof(Playlist).Name }; query.IncludeItemTypes = new[] { nameof(Playlist) };
query.SetUser(user); query.SetUser(user);
query.Recursive = true; query.Recursive = true;
@ -1132,10 +1138,9 @@ namespace Emby.Dlna.ContentDirectory
{ {
UserId = user.Id, UserId = user.Id,
Limit = 50, Limit = 50,
IncludeItemTypes = new[] { typeof(Audio).Name }, IncludeItemTypes = new[] { nameof(Audio) },
ParentId = parent == null ? Guid.Empty : parent.Id, ParentId = parent?.Id ?? Guid.Empty,
GroupItems = true GroupItems = true
}, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray(); }, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray();
return ToResult(items); return ToResult(items);
@ -1150,7 +1155,6 @@ namespace Emby.Dlna.ContentDirectory
Limit = query.Limit, Limit = query.Limit,
StartIndex = query.StartIndex, StartIndex = query.StartIndex,
UserId = query.User.Id UserId = query.User.Id
}, new[] { parent }, query.DtoOptions); }, new[] { parent }, query.DtoOptions);
return ToResult(result); return ToResult(result);
@ -1167,7 +1171,6 @@ namespace Emby.Dlna.ContentDirectory
IncludeItemTypes = new[] { typeof(Episode).Name }, IncludeItemTypes = new[] { typeof(Episode).Name },
ParentId = parent == null ? Guid.Empty : parent.Id, ParentId = parent == null ? Guid.Empty : parent.Id,
GroupItems = false GroupItems = false
}, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray(); }, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray();
return ToResult(items); return ToResult(items);
@ -1177,14 +1180,14 @@ namespace Emby.Dlna.ContentDirectory
{ {
query.OrderBy = Array.Empty<(string, SortOrder)>(); query.OrderBy = Array.Empty<(string, SortOrder)>();
var items = _userViewManager.GetLatestItems(new LatestItemsQuery var items = _userViewManager.GetLatestItems(
new LatestItemsQuery
{ {
UserId = user.Id, UserId = user.Id,
Limit = 50, Limit = 50,
IncludeItemTypes = new[] { typeof(Movie).Name }, IncludeItemTypes = new[] { nameof(Movie) },
ParentId = parent == null ? Guid.Empty : parent.Id, ParentId = parent?.Id ?? Guid.Empty,
GroupItems = true GroupItems = true
}, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray(); }, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray();
return ToResult(items); return ToResult(items);
@ -1217,7 +1220,11 @@ namespace Emby.Dlna.ContentDirectory
Recursive = true, Recursive = true,
ParentId = parentId, ParentId = parentId,
GenreIds = new[] { item.Id }, GenreIds = new[] { item.Id },
IncludeItemTypes = new[] { typeof(Movie).Name, typeof(Series).Name }, IncludeItemTypes = new[]
{
nameof(Movie),
nameof(Series)
},
Limit = limit, Limit = limit,
StartIndex = startIndex, StartIndex = startIndex,
DtoOptions = GetDtoOptions() DtoOptions = GetDtoOptions()

View File

@ -6,14 +6,13 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Xml; using System.Xml;
using Emby.Dlna.Configuration;
using Emby.Dlna.ContentDirectory; using Emby.Dlna.ContentDirectory;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Playlists; using MediaBrowser.Controller.Playlists;
@ -23,6 +22,13 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Net; using MediaBrowser.Model.Net;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
using Genre = MediaBrowser.Controller.Entities.Genre;
using Movie = MediaBrowser.Controller.Entities.Movies.Movie;
using MusicAlbum = MediaBrowser.Controller.Entities.Audio.MusicAlbum;
using Season = MediaBrowser.Controller.Entities.TV.Season;
using Series = MediaBrowser.Controller.Entities.TV.Series;
using XmlAttribute = MediaBrowser.Model.Dlna.XmlAttribute;
namespace Emby.Dlna.Didl namespace Emby.Dlna.Didl
{ {
@ -421,7 +427,6 @@ namespace Emby.Dlna.Didl
case StubType.FavoriteSeries: return _localization.GetLocalizedString("HeaderFavoriteShows"); case StubType.FavoriteSeries: return _localization.GetLocalizedString("HeaderFavoriteShows");
case StubType.FavoriteEpisodes: return _localization.GetLocalizedString("HeaderFavoriteEpisodes"); case StubType.FavoriteEpisodes: return _localization.GetLocalizedString("HeaderFavoriteEpisodes");
case StubType.Series: return _localization.GetLocalizedString("Shows"); case StubType.Series: return _localization.GetLocalizedString("Shows");
default: break;
} }
} }
@ -670,7 +675,7 @@ namespace Emby.Dlna.Didl
return; return;
} }
MediaBrowser.Model.Dlna.XmlAttribute secAttribute = null; XmlAttribute secAttribute = null;
foreach (var attribute in _profile.XmlRootAttributes) foreach (var attribute in _profile.XmlRootAttributes)
{ {
if (string.Equals(attribute.Name, "xmlns:sec", StringComparison.OrdinalIgnoreCase)) if (string.Equals(attribute.Name, "xmlns:sec", StringComparison.OrdinalIgnoreCase))
@ -995,7 +1000,6 @@ namespace Emby.Dlna.Didl
} }
AddImageResElement(item, writer, 160, 160, "jpg", "JPEG_TN"); AddImageResElement(item, writer, 160, 160, "jpg", "JPEG_TN");
} }
private void AddImageResElement( private void AddImageResElement(
@ -1135,7 +1139,6 @@ namespace Emby.Dlna.Didl
width = null; width = null;
height = null; height = null;
} }
else if (width == -1 || height == -1) else if (width == -1 || height == -1)
{ {
width = null; width = null;

View File

@ -12,7 +12,6 @@ namespace Emby.Dlna.Didl
public Filter() public Filter()
: this("*") : this("*")
{ {
} }
public Filter(string filter) public Filter(string filter)

View File

@ -88,7 +88,6 @@ namespace Emby.Dlna
.Select(i => i.Item2) .Select(i => i.Item2)
.ToList(); .ToList();
} }
} }
public DeviceProfile GetDefaultProfile() public DeviceProfile GetDefaultProfile()

View File

@ -169,7 +169,6 @@ namespace Emby.Dlna.Eventing
{ {
using (await _httpClient.SendAsync(options, new HttpMethod("NOTIFY")).ConfigureAwait(false)) using (await _httpClient.SendAsync(options, new HttpMethod("NOTIFY")).ConfigureAwait(false))
{ {
} }
} }
catch (OperationCanceledException) catch (OperationCanceledException)

View File

@ -794,7 +794,6 @@ namespace Emby.Dlna.PlayTo
} }
catch (XmlException) catch (XmlException)
{ {
} }
// first try to add a root node with a dlna namesapce // first try to add a root node with a dlna namesapce
@ -806,7 +805,6 @@ namespace Emby.Dlna.PlayTo
} }
catch (XmlException) catch (XmlException)
{ {
} }
// some devices send back invalid xml // some devices send back invalid xml
@ -816,7 +814,6 @@ namespace Emby.Dlna.PlayTo
} }
catch (XmlException) catch (XmlException)
{ {
} }
return null; return null;

View File

@ -7,6 +7,7 @@ using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Emby.Dlna.Didl; using Emby.Dlna.Didl;
using Jellyfin.Data.Entities;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Drawing;
@ -22,6 +23,7 @@ using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Session; using MediaBrowser.Model.Session;
using Microsoft.AspNetCore.WebUtilities; using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Photo = MediaBrowser.Controller.Entities.Photo;
namespace Emby.Dlna.PlayTo namespace Emby.Dlna.PlayTo
{ {
@ -446,7 +448,13 @@ namespace Emby.Dlna.PlayTo
} }
} }
private PlaylistItem CreatePlaylistItem(BaseItem item, User user, long startPostionTicks, string mediaSourceId, int? audioStreamIndex, int? subtitleStreamIndex) private PlaylistItem CreatePlaylistItem(
BaseItem item,
User user,
long startPostionTicks,
string mediaSourceId,
int? audioStreamIndex,
int? subtitleStreamIndex)
{ {
var deviceInfo = _device.Properties; var deviceInfo = _device.Properties;

View File

@ -112,7 +112,6 @@ namespace Emby.Dlna.PlayTo
} }
catch (OperationCanceledException) catch (OperationCanceledException)
{ {
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -243,7 +242,6 @@ namespace Emby.Dlna.PlayTo
} }
catch catch
{ {
} }
_sessionLock.Dispose(); _sessionLock.Dispose();

View File

@ -91,7 +91,6 @@ namespace Emby.Dlna.PlayTo
using (await _httpClient.SendAsync(options, new HttpMethod("SUBSCRIBE")).ConfigureAwait(false)) using (await _httpClient.SendAsync(options, new HttpMethod("SUBSCRIBE")).ConfigureAwait(false))
{ {
} }
} }

View File

@ -4,6 +4,7 @@ using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller; using MediaBrowser.Controller;
using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Drawing;
@ -14,6 +15,7 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net; using MediaBrowser.Model.Net;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Photo = MediaBrowser.Controller.Entities.Photo;
namespace Emby.Drawing namespace Emby.Drawing
{ {
@ -349,6 +351,13 @@ namespace Emby.Drawing
}); });
} }
/// <inheritdoc />
public string GetImageCacheTag(User user)
{
return (user.ProfileImage.Path + user.ProfileImage.LastModified.Ticks).GetMD5()
.ToString("N", CultureInfo.InvariantCulture);
}
private async Task<(string path, DateTime dateModified)> GetSupportedImage(string originalImagePath, DateTime dateModified) private async Task<(string path, DateTime dateModified)> GetSupportedImage(string originalImagePath, DateTime dateModified)
{ {
var inputFormat = Path.GetExtension(originalImagePath) var inputFormat = Path.GetExtension(originalImagePath)

View File

@ -8,6 +8,7 @@ using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Notifications; using MediaBrowser.Controller.Notifications;
@ -149,9 +150,7 @@ namespace Emby.Notifications.Api
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification = "Required for ServiceStack")]
public object Get(GetNotificationsSummary request) public object Get(GetNotificationsSummary request)
{ {
return new NotificationsSummary return new NotificationsSummary();
{
};
} }
public Task Post(AddAdminNotification request) public Task Post(AddAdminNotification request)
@ -164,7 +163,10 @@ namespace Emby.Notifications.Api
Level = request.Level, Level = request.Level,
Name = request.Name, Name = request.Name,
Url = request.Url, Url = request.Url,
UserIds = _userManager.Users.Where(i => i.Policy.IsAdministrator).Select(i => i.Id).ToArray() UserIds = _userManager.Users
.Where(user => user.HasPermission(PermissionKind.IsAdministrator))
.Select(user => user.Id)
.ToArray()
}; };
return _notificationManager.SendNotification(notification, CancellationToken.None); return _notificationManager.SendNotification(notification, CancellationToken.None);

View File

@ -4,6 +4,8 @@ using System.Globalization;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
@ -101,7 +103,7 @@ namespace Emby.Notifications
switch (request.SendToUserMode.Value) switch (request.SendToUserMode.Value)
{ {
case SendToUserType.Admins: case SendToUserType.Admins:
return _userManager.Users.Where(i => i.Policy.IsAdministrator) return _userManager.Users.Where(i => i.HasPermission(PermissionKind.IsAdministrator))
.Select(i => i.Id); .Select(i => i.Id);
case SendToUserType.All: case SendToUserType.All:
return _userManager.UsersIds; return _userManager.UsersIds;
@ -117,7 +119,7 @@ namespace Emby.Notifications
var config = GetConfiguration(); var config = GetConfiguration();
return _userManager.Users return _userManager.Users
.Where(i => config.IsEnabledToSendToUser(request.NotificationType, i.Id.ToString("N", CultureInfo.InvariantCulture), i.Policy)) .Where(i => config.IsEnabledToSendToUser(request.NotificationType, i.Id.ToString("N", CultureInfo.InvariantCulture), i))
.Select(i => i.Id); .Select(i => i.Id);
} }
@ -142,7 +144,7 @@ namespace Emby.Notifications
User = user User = user
}; };
_logger.LogDebug("Sending notification via {0} to user {1}", service.Name, user.Name); _logger.LogDebug("Sending notification via {0} to user {1}", service.Name, user.Username);
try try
{ {

View File

@ -88,25 +88,26 @@ namespace Emby.Server.Implementations.Activity
_subManager.SubtitleDownloadFailure += OnSubtitleDownloadFailure; _subManager.SubtitleDownloadFailure += OnSubtitleDownloadFailure;
_userManager.UserCreated += OnUserCreated; _userManager.OnUserCreated += OnUserCreated;
_userManager.UserPasswordChanged += OnUserPasswordChanged; _userManager.OnUserPasswordChanged += OnUserPasswordChanged;
_userManager.UserDeleted += OnUserDeleted; _userManager.OnUserDeleted += OnUserDeleted;
_userManager.UserPolicyUpdated += OnUserPolicyUpdated; _userManager.OnUserLockedOut += OnUserLockedOut;
_userManager.UserLockedOut += OnUserLockedOut;
return Task.CompletedTask; return Task.CompletedTask;
} }
private async void OnUserLockedOut(object sender, GenericEventArgs<MediaBrowser.Controller.Entities.User> e) private async void OnUserLockedOut(object sender, GenericEventArgs<User> e)
{ {
await CreateLogEntry(new ActivityLog( await CreateLogEntry(new ActivityLog(
string.Format( string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
_localization.GetLocalizedString("UserLockedOutWithName"), _localization.GetLocalizedString("UserLockedOutWithName"),
e.Argument.Name), e.Argument.Username),
NotificationType.UserLockedOut.ToString(), NotificationType.UserLockedOut.ToString(),
e.Argument.Id)) e.Argument.Id)
.ConfigureAwait(false); {
LogSeverity = LogLevel.Error
}).ConfigureAwait(false);
} }
private async void OnSubtitleDownloadFailure(object sender, SubtitleDownloadFailureEventArgs e) private async void OnSubtitleDownloadFailure(object sender, SubtitleDownloadFailureEventArgs e)
@ -152,7 +153,7 @@ namespace Emby.Server.Implementations.Activity
string.Format( string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
_localization.GetLocalizedString("UserStoppedPlayingItemWithValues"), _localization.GetLocalizedString("UserStoppedPlayingItemWithValues"),
user.Name, user.Username,
GetItemName(item), GetItemName(item),
e.DeviceName), e.DeviceName),
GetPlaybackStoppedNotificationType(item.MediaType), GetPlaybackStoppedNotificationType(item.MediaType),
@ -187,7 +188,7 @@ namespace Emby.Server.Implementations.Activity
string.Format( string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
_localization.GetLocalizedString("UserStartedPlayingItemWithValues"), _localization.GetLocalizedString("UserStartedPlayingItemWithValues"),
user.Name, user.Username,
GetItemName(item), GetItemName(item),
e.DeviceName), e.DeviceName),
GetPlaybackNotificationType(item.MediaType), GetPlaybackNotificationType(item.MediaType),
@ -304,49 +305,37 @@ namespace Emby.Server.Implementations.Activity
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
private async void OnUserPolicyUpdated(object sender, GenericEventArgs<MediaBrowser.Controller.Entities.User> e) private async void OnUserDeleted(object sender, GenericEventArgs<User> e)
{
await CreateLogEntry(new ActivityLog(
string.Format(
CultureInfo.InvariantCulture,
_localization.GetLocalizedString("UserPolicyUpdatedWithName"),
e.Argument.Name),
"UserPolicyUpdated",
e.Argument.Id))
.ConfigureAwait(false);
}
private async void OnUserDeleted(object sender, GenericEventArgs<MediaBrowser.Controller.Entities.User> e)
{ {
await CreateLogEntry(new ActivityLog( await CreateLogEntry(new ActivityLog(
string.Format( string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
_localization.GetLocalizedString("UserDeletedWithName"), _localization.GetLocalizedString("UserDeletedWithName"),
e.Argument.Name), e.Argument.Username),
"UserDeleted", "UserDeleted",
Guid.Empty)) Guid.Empty))
.ConfigureAwait(false); .ConfigureAwait(false);
} }
private async void OnUserPasswordChanged(object sender, GenericEventArgs<MediaBrowser.Controller.Entities.User> e) private async void OnUserPasswordChanged(object sender, GenericEventArgs<User> e)
{ {
await CreateLogEntry(new ActivityLog( await CreateLogEntry(new ActivityLog(
string.Format( string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
_localization.GetLocalizedString("UserPasswordChangedWithName"), _localization.GetLocalizedString("UserPasswordChangedWithName"),
e.Argument.Name), e.Argument.Username),
"UserPasswordChanged", "UserPasswordChanged",
e.Argument.Id)) e.Argument.Id))
.ConfigureAwait(false); .ConfigureAwait(false);
} }
private async void OnUserCreated(object sender, GenericEventArgs<MediaBrowser.Controller.Entities.User> e) private async void OnUserCreated(object sender, GenericEventArgs<User> e)
{ {
await CreateLogEntry(new ActivityLog( await CreateLogEntry(new ActivityLog(
string.Format( string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
_localization.GetLocalizedString("UserCreatedWithName"), _localization.GetLocalizedString("UserCreatedWithName"),
e.Argument.Name), e.Argument.Username),
"UserCreated", "UserCreated",
e.Argument.Id)) e.Argument.Id))
.ConfigureAwait(false); .ConfigureAwait(false);
@ -510,11 +499,10 @@ namespace Emby.Server.Implementations.Activity
_subManager.SubtitleDownloadFailure -= OnSubtitleDownloadFailure; _subManager.SubtitleDownloadFailure -= OnSubtitleDownloadFailure;
_userManager.UserCreated -= OnUserCreated; _userManager.OnUserCreated -= OnUserCreated;
_userManager.UserPasswordChanged -= OnUserPasswordChanged; _userManager.OnUserPasswordChanged -= OnUserPasswordChanged;
_userManager.UserDeleted -= OnUserDeleted; _userManager.OnUserDeleted -= OnUserDeleted;
_userManager.UserPolicyUpdated -= OnUserPolicyUpdated; _userManager.OnUserLockedOut -= OnUserLockedOut;
_userManager.UserLockedOut -= OnUserLockedOut;
} }
/// <summary> /// <summary>

View File

@ -562,11 +562,8 @@ namespace Emby.Server.Implementations
serviceCollection.AddSingleton<IAuthenticationRepository, AuthenticationRepository>(); serviceCollection.AddSingleton<IAuthenticationRepository, AuthenticationRepository>();
serviceCollection.AddSingleton<IUserRepository, SqliteUserRepository>();
// TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required // TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required
serviceCollection.AddTransient(provider => new Lazy<IDtoService>(provider.GetRequiredService<IDtoService>)); serviceCollection.AddTransient(provider => new Lazy<IDtoService>(provider.GetRequiredService<IDtoService>));
serviceCollection.AddSingleton<IUserManager, UserManager>();
// TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required // TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required
// TODO: Add StartupOptions.FFmpegPath to IConfiguration and remove this custom activation // TODO: Add StartupOptions.FFmpegPath to IConfiguration and remove this custom activation
@ -659,15 +656,11 @@ namespace Emby.Server.Implementations
((SqliteDisplayPreferencesRepository)Resolve<IDisplayPreferencesRepository>()).Initialize(); ((SqliteDisplayPreferencesRepository)Resolve<IDisplayPreferencesRepository>()).Initialize();
((AuthenticationRepository)Resolve<IAuthenticationRepository>()).Initialize(); ((AuthenticationRepository)Resolve<IAuthenticationRepository>()).Initialize();
((SqliteUserRepository)Resolve<IUserRepository>()).Initialize();
SetStaticProperties(); SetStaticProperties();
var userManager = (UserManager)Resolve<IUserManager>();
userManager.Initialize();
var userDataRepo = (SqliteUserDataRepository)Resolve<IUserDataRepository>(); var userDataRepo = (SqliteUserDataRepository)Resolve<IUserDataRepository>();
((SqliteItemRepository)Resolve<IItemRepository>()).Initialize(userDataRepo, userManager); ((SqliteItemRepository)Resolve<IItemRepository>()).Initialize(userDataRepo, Resolve<IUserManager>());
FindParts(); FindParts();
} }
@ -750,7 +743,6 @@ namespace Emby.Server.Implementations
BaseItem.ProviderManager = Resolve<IProviderManager>(); BaseItem.ProviderManager = Resolve<IProviderManager>();
BaseItem.LocalizationManager = Resolve<ILocalizationManager>(); BaseItem.LocalizationManager = Resolve<ILocalizationManager>();
BaseItem.ItemRepository = Resolve<IItemRepository>(); BaseItem.ItemRepository = Resolve<IItemRepository>();
User.UserManager = Resolve<IUserManager>();
BaseItem.FileSystem = _fileSystemManager; BaseItem.FileSystem = _fileSystemManager;
BaseItem.UserDataManager = Resolve<IUserDataManager>(); BaseItem.UserDataManager = Resolve<IUserDataManager>();
BaseItem.ChannelManager = Resolve<IChannelManager>(); BaseItem.ChannelManager = Resolve<IChannelManager>();

View File

@ -6,6 +6,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Progress; using MediaBrowser.Common.Progress;
using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Channels;
@ -13,8 +14,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Channels; using MediaBrowser.Model.Channels;
@ -24,6 +23,11 @@ using MediaBrowser.Model.IO;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Serialization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
using Movie = MediaBrowser.Controller.Entities.Movies.Movie;
using MusicAlbum = MediaBrowser.Controller.Entities.Audio.MusicAlbum;
using Season = MediaBrowser.Controller.Entities.TV.Season;
using Series = MediaBrowser.Controller.Entities.TV.Series;
namespace Emby.Server.Implementations.Channels namespace Emby.Server.Implementations.Channels
{ {
@ -791,7 +795,8 @@ namespace Emby.Server.Implementations.Channels
return result; return result;
} }
private async Task<ChannelItemResult> GetChannelItems(IChannel channel, private async Task<ChannelItemResult> GetChannelItems(
IChannel channel,
User user, User user,
string externalFolderId, string externalFolderId,
ChannelItemSortField? sortField, ChannelItemSortField? sortField,

View File

@ -5,6 +5,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Collections; using MediaBrowser.Controller.Collections;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;

View File

@ -162,7 +162,6 @@ namespace Emby.Server.Implementations.Data
} }
return false; return false;
}, ReadTransactionMode); }, ReadTransactionMode);
} }

View File

@ -51,7 +51,6 @@ namespace Emby.Server.Implementations.Data
_libraryManager.DeleteItem(item, new DeleteOptions _libraryManager.DeleteItem(item, new DeleteOptions
{ {
DeleteFileLocation = false DeleteFileLocation = false
}); });
} }

View File

@ -1,4 +1,4 @@
#pragma warning disable CS1591 #pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;

View File

@ -321,7 +321,6 @@ namespace Emby.Server.Implementations.Data
AddColumn(db, "MediaStreams", "ColorPrimaries", "TEXT", existingColumnNames); AddColumn(db, "MediaStreams", "ColorPrimaries", "TEXT", existingColumnNames);
AddColumn(db, "MediaStreams", "ColorSpace", "TEXT", existingColumnNames); AddColumn(db, "MediaStreams", "ColorSpace", "TEXT", existingColumnNames);
AddColumn(db, "MediaStreams", "ColorTransfer", "TEXT", existingColumnNames); AddColumn(db, "MediaStreams", "ColorTransfer", "TEXT", existingColumnNames);
}, TransactionMode); }, TransactionMode);
connection.RunQueries(postQueries); connection.RunQueries(postQueries);
@ -2044,7 +2043,6 @@ namespace Emby.Server.Implementations.Data
db.Execute("delete from " + ChaptersTableName + " where ItemId=@ItemId", idBlob); db.Execute("delete from " + ChaptersTableName + " where ItemId=@ItemId", idBlob);
InsertChapters(idBlob, chapters, db); InsertChapters(idBlob, chapters, db);
}, TransactionMode); }, TransactionMode);
} }
} }
@ -4789,7 +4787,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
connection.RunInTransaction(db => connection.RunInTransaction(db =>
{ {
connection.ExecuteAll(sql); connection.ExecuteAll(sql);
}, TransactionMode); }, TransactionMode);
} }
} }
@ -5180,7 +5177,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
} }
} }
} }
} }
LogQueryTime("GetItemValueNames", commandText, now); LogQueryTime("GetItemValueNames", commandText, now);
@ -5631,7 +5627,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
db.Execute("delete from People where ItemId=@ItemId", itemIdBlob); db.Execute("delete from People where ItemId=@ItemId", itemIdBlob);
InsertPeople(itemIdBlob, people, db); InsertPeople(itemIdBlob, people, db);
}, TransactionMode); }, TransactionMode);
} }
} }
@ -5788,7 +5783,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
db.Execute("delete from mediastreams where ItemId=@ItemId", itemIdBlob); db.Execute("delete from mediastreams where ItemId=@ItemId", itemIdBlob);
InsertMediaStreams(itemIdBlob, streams, db); InsertMediaStreams(itemIdBlob, streams, db);
}, TransactionMode); }, TransactionMode);
} }
} }
@ -6134,7 +6128,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
db.Execute("delete from mediaattachments where ItemId=@ItemId", itemIdBlob); db.Execute("delete from mediaattachments where ItemId=@ItemId", itemIdBlob);
InsertMediaAttachments(itemIdBlob, attachments, db, cancellationToken); InsertMediaAttachments(itemIdBlob, attachments, db, cancellationToken);
}, TransactionMode); }, TransactionMode);
} }
} }

View File

@ -4,6 +4,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using Jellyfin.Data.Entities;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;

View File

@ -1,240 +0,0 @@
#pragma warning disable CS1591
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using MediaBrowser.Common.Json;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Persistence;
using Microsoft.Extensions.Logging;
using SQLitePCL.pretty;
namespace Emby.Server.Implementations.Data
{
/// <summary>
/// Class SQLiteUserRepository
/// </summary>
public class SqliteUserRepository : BaseSqliteRepository, IUserRepository
{
private readonly JsonSerializerOptions _jsonOptions;
public SqliteUserRepository(
ILogger<SqliteUserRepository> logger,
IServerApplicationPaths appPaths)
: base(logger)
{
_jsonOptions = JsonDefaults.GetOptions();
DbFilePath = Path.Combine(appPaths.DataPath, "users.db");
}
/// <summary>
/// Gets the name of the repository
/// </summary>
/// <value>The name.</value>
public string Name => "SQLite";
/// <summary>
/// Opens the connection to the database.
/// </summary>
public void Initialize()
{
using (var connection = GetConnection())
{
var localUsersTableExists = TableExists(connection, "LocalUsersv2");
connection.RunQueries(new[] {
"create table if not exists LocalUsersv2 (Id INTEGER PRIMARY KEY, guid GUID NOT NULL, data BLOB NOT NULL)",
"drop index if exists idx_users"
});
if (!localUsersTableExists && TableExists(connection, "Users"))
{
TryMigrateToLocalUsersTable(connection);
}
RemoveEmptyPasswordHashes(connection);
}
}
private void TryMigrateToLocalUsersTable(ManagedConnection connection)
{
try
{
connection.RunQueries(new[]
{
"INSERT INTO LocalUsersv2 (guid, data) SELECT guid,data from users"
});
}
catch (Exception ex)
{
Logger.LogError(ex, "Error migrating users database");
}
}
private void RemoveEmptyPasswordHashes(ManagedConnection connection)
{
foreach (var user in RetrieveAllUsers(connection))
{
// If the user password is the sha1 hash of the empty string, remove it
if (!string.Equals(user.Password, "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709", StringComparison.Ordinal)
&& !string.Equals(user.Password, "$SHA1$DA39A3EE5E6B4B0D3255BFEF95601890AFD80709", StringComparison.Ordinal))
{
continue;
}
user.Password = null;
var serialized = JsonSerializer.SerializeToUtf8Bytes(user, _jsonOptions);
connection.RunInTransaction(db =>
{
using (var statement = db.PrepareStatement("update LocalUsersv2 set data=@data where Id=@InternalId"))
{
statement.TryBind("@InternalId", user.InternalId);
statement.TryBind("@data", serialized);
statement.MoveNext();
}
}, TransactionMode);
}
}
/// <summary>
/// Save a user in the repo
/// </summary>
public void CreateUser(User user)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
var serialized = JsonSerializer.SerializeToUtf8Bytes(user, _jsonOptions);
using (var connection = GetConnection())
{
connection.RunInTransaction(db =>
{
using (var statement = db.PrepareStatement("insert into LocalUsersv2 (guid, data) values (@guid, @data)"))
{
statement.TryBind("@guid", user.Id.ToByteArray());
statement.TryBind("@data", serialized);
statement.MoveNext();
}
var createdUser = GetUser(user.Id, connection);
if (createdUser == null)
{
throw new ApplicationException("created user should never be null");
}
user.InternalId = createdUser.InternalId;
}, TransactionMode);
}
}
public void UpdateUser(User user)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
var serialized = JsonSerializer.SerializeToUtf8Bytes(user, _jsonOptions);
using (var connection = GetConnection())
{
connection.RunInTransaction(db =>
{
using (var statement = db.PrepareStatement("update LocalUsersv2 set data=@data where Id=@InternalId"))
{
statement.TryBind("@InternalId", user.InternalId);
statement.TryBind("@data", serialized);
statement.MoveNext();
}
}, TransactionMode);
}
}
private User GetUser(Guid guid, ManagedConnection connection)
{
using (var statement = connection.PrepareStatement("select id,guid,data from LocalUsersv2 where guid=@guid"))
{
statement.TryBind("@guid", guid);
foreach (var row in statement.ExecuteQuery())
{
return GetUser(row);
}
}
return null;
}
private User GetUser(IReadOnlyList<IResultSetValue> row)
{
var id = row[0].ToInt64();
var guid = row[1].ReadGuidFromBlob();
var user = JsonSerializer.Deserialize<User>(row[2].ToBlob(), _jsonOptions);
user.InternalId = id;
user.Id = guid;
return user;
}
/// <summary>
/// Retrieve all users from the database
/// </summary>
/// <returns>IEnumerable{User}.</returns>
public List<User> RetrieveAllUsers()
{
using (var connection = GetConnection(true))
{
return new List<User>(RetrieveAllUsers(connection));
}
}
/// <summary>
/// Retrieve all users from the database
/// </summary>
/// <returns>IEnumerable{User}.</returns>
private IEnumerable<User> RetrieveAllUsers(ManagedConnection connection)
{
foreach (var row in connection.Query("select id,guid,data from LocalUsersv2"))
{
yield return GetUser(row);
}
}
/// <summary>
/// Deletes the user.
/// </summary>
/// <param name="user">The user.</param>
/// <returns>Task.</returns>
/// <exception cref="ArgumentNullException">user</exception>
public void DeleteUser(User user)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
using (var connection = GetConnection())
{
connection.RunInTransaction(db =>
{
using (var statement = db.PrepareStatement("delete from LocalUsersv2 where Id=@id"))
{
statement.TryBind("@id", user.InternalId);
statement.MoveNext();
}
}, TransactionMode);
}
}
}
}

View File

@ -5,10 +5,11 @@ using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Jellyfin.Data.Enums;
using Jellyfin.Data.Entities;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Security;
using MediaBrowser.Model.Devices; using MediaBrowser.Model.Devices;
@ -16,7 +17,6 @@ using MediaBrowser.Model.Events;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Session; using MediaBrowser.Model.Session;
using MediaBrowser.Model.Users;
namespace Emby.Server.Implementations.Devices namespace Emby.Server.Implementations.Devices
{ {
@ -27,11 +27,10 @@ namespace Emby.Server.Implementations.Devices
private readonly IServerConfigurationManager _config; private readonly IServerConfigurationManager _config;
private readonly IAuthenticationRepository _authRepo; private readonly IAuthenticationRepository _authRepo;
private readonly Dictionary<string, ClientCapabilities> _capabilitiesCache; private readonly Dictionary<string, ClientCapabilities> _capabilitiesCache;
private readonly object _capabilitiesSyncLock = new object();
public event EventHandler<GenericEventArgs<Tuple<string, DeviceOptions>>> DeviceOptionsUpdated; public event EventHandler<GenericEventArgs<Tuple<string, DeviceOptions>>> DeviceOptionsUpdated;
private readonly object _capabilitiesSyncLock = new object();
public DeviceManager( public DeviceManager(
IAuthenticationRepository authRepo, IAuthenticationRepository authRepo,
IJsonSerializer json, IJsonSerializer json,
@ -175,7 +174,12 @@ namespace Emby.Server.Implementations.Devices
throw new ArgumentNullException(nameof(deviceId)); throw new ArgumentNullException(nameof(deviceId));
} }
if (!CanAccessDevice(user.Policy, deviceId)) if (user.HasPermission(PermissionKind.EnableAllDevices) || user.HasPermission(PermissionKind.IsAdministrator))
{
return true;
}
if (!user.GetPreference(PreferenceKind.EnabledDevices).Contains(deviceId, StringComparer.OrdinalIgnoreCase))
{ {
var capabilities = GetCapabilities(deviceId); var capabilities = GetCapabilities(deviceId);
@ -187,20 +191,5 @@ namespace Emby.Server.Implementations.Devices
return true; return true;
} }
private static bool CanAccessDevice(UserPolicy policy, string id)
{
if (policy.EnableAllDevices)
{
return true;
}
if (policy.IsAdministrator)
{
return true;
}
return policy.EnabledDevices.Contains(id, StringComparer.OrdinalIgnoreCase);
}
} }
} }

View File

@ -6,14 +6,14 @@ using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common; using MediaBrowser.Common;
using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Persistence;
@ -24,6 +24,14 @@ using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Book = MediaBrowser.Controller.Entities.Book;
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
using Movie = MediaBrowser.Controller.Entities.Movies.Movie;
using MusicAlbum = MediaBrowser.Controller.Entities.Audio.MusicAlbum;
using Person = MediaBrowser.Controller.Entities.Person;
using Photo = MediaBrowser.Controller.Entities.Photo;
using Season = MediaBrowser.Controller.Entities.TV.Season;
using Series = MediaBrowser.Controller.Entities.TV.Series;
namespace Emby.Server.Implementations.Dto namespace Emby.Server.Implementations.Dto
{ {
@ -384,7 +392,7 @@ namespace Emby.Server.Implementations.Dto
if (options.ContainsField(ItemFields.ChildCount)) if (options.ContainsField(ItemFields.ChildCount))
{ {
dto.ChildCount = dto.ChildCount ?? GetChildCount(folder, user); dto.ChildCount ??= GetChildCount(folder, user);
} }
} }
@ -398,7 +406,6 @@ namespace Emby.Server.Implementations.Dto
dto.DateLastMediaAdded = folder.DateLastMediaAdded; dto.DateLastMediaAdded = folder.DateLastMediaAdded;
} }
} }
else else
{ {
if (options.EnableUserData) if (options.EnableUserData)
@ -414,7 +421,7 @@ namespace Emby.Server.Implementations.Dto
if (options.ContainsField(ItemFields.BasicSyncInfo)) if (options.ContainsField(ItemFields.BasicSyncInfo))
{ {
var userCanSync = user != null && user.Policy.EnableContentDownloading; var userCanSync = user != null && user.HasPermission(PermissionKind.EnableContentDownloading);
if (userCanSync && item.SupportsExternalTransfer) if (userCanSync && item.SupportsExternalTransfer)
{ {
dto.SupportsSync = true; dto.SupportsSync = true;
@ -586,7 +593,6 @@ namespace Emby.Server.Implementations.Dto
_logger.LogError(ex, "Error getting person {Name}", c); _logger.LogError(ex, "Error getting person {Name}", c);
return null; return null;
} }
}).Where(i => i != null) }).Where(i => i != null)
.GroupBy(i => i.Name, StringComparer.OrdinalIgnoreCase) .GroupBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
.Select(x => x.First()) .Select(x => x.First())
@ -993,7 +999,6 @@ namespace Emby.Server.Implementations.Dto
} }
return null; return null;
}).Where(i => i != null).ToArray(); }).Where(i => i != null).ToArray();
} }
@ -1044,7 +1049,6 @@ namespace Emby.Server.Implementations.Dto
} }
return null; return null;
}).Where(i => i != null).ToArray(); }).Where(i => i != null).ToArray();
} }

View File

@ -6,6 +6,7 @@ using System.Globalization;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Audio;
@ -131,7 +132,6 @@ namespace Emby.Server.Implementations.EntryPoints
} }
catch catch
{ {
} }
} }
} }

View File

@ -4,6 +4,7 @@ using System;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Plugins;
@ -64,7 +65,7 @@ namespace Emby.Server.Implementations.EntryPoints
private async Task SendMessage(string name, TimerEventInfo info) private async Task SendMessage(string name, TimerEventInfo info)
{ {
var users = _userManager.Users.Where(i => i.Policy.EnableLiveTvAccess).Select(i => i.Id).ToList(); var users = _userManager.Users.Where(i => i.HasPermission(PermissionKind.EnableLiveTvAccess)).Select(i => i.Id).ToList();
try try
{ {

View File

@ -1,77 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Tasks;
namespace Emby.Server.Implementations.EntryPoints
{
/// <summary>
/// Class RefreshUsersMetadata.
/// </summary>
public class RefreshUsersMetadata : IScheduledTask, IConfigurableScheduledTask
{
/// <summary>
/// The user manager.
/// </summary>
private readonly IUserManager _userManager;
private readonly IFileSystem _fileSystem;
/// <summary>
/// Initializes a new instance of the <see cref="RefreshUsersMetadata" /> class.
/// </summary>
public RefreshUsersMetadata(IUserManager userManager, IFileSystem fileSystem)
{
_userManager = userManager;
_fileSystem = fileSystem;
}
/// <inheritdoc />
public string Name => "Refresh Users";
/// <inheritdoc />
public string Key => "RefreshUsers";
/// <inheritdoc />
public string Description => "Refresh user infos";
/// <inheritdoc />
public string Category => "Library";
/// <inheritdoc />
public bool IsHidden => true;
/// <inheritdoc />
public bool IsEnabled => true;
/// <inheritdoc />
public bool IsLogged => true;
/// <inheritdoc />
public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
{
foreach (var user in _userManager.Users)
{
cancellationToken.ThrowIfCancellationRequested();
await user.RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(_fileSystem)), cancellationToken).ConfigureAwait(false);
}
}
/// <inheritdoc />
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
{
return new[]
{
new TaskTriggerInfo
{
IntervalTicks = TimeSpan.FromDays(1).Ticks,
Type = TaskTriggerInfo.TriggerInterval
}
};
}
}
}

View File

@ -3,10 +3,10 @@ using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Plugins;
using MediaBrowser.Common.Updates; using MediaBrowser.Common.Updates;
using MediaBrowser.Controller; using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Session;
@ -68,10 +68,8 @@ namespace Emby.Server.Implementations.EntryPoints
/// <inheritdoc /> /// <inheritdoc />
public Task RunAsync() public Task RunAsync()
{ {
_userManager.UserDeleted += OnUserDeleted; _userManager.OnUserDeleted += OnUserDeleted;
_userManager.UserUpdated += OnUserUpdated; _userManager.OnUserUpdated += OnUserUpdated;
_userManager.UserPolicyUpdated += OnUserPolicyUpdated;
_userManager.UserConfigurationUpdated += OnUserConfigurationUpdated;
_appHost.HasPendingRestartChanged += OnHasPendingRestartChanged; _appHost.HasPendingRestartChanged += OnHasPendingRestartChanged;
@ -153,20 +151,6 @@ namespace Emby.Server.Implementations.EntryPoints
await SendMessageToUserSession(e.Argument, "UserDeleted", e.Argument.Id.ToString("N", CultureInfo.InvariantCulture)).ConfigureAwait(false); await SendMessageToUserSession(e.Argument, "UserDeleted", e.Argument.Id.ToString("N", CultureInfo.InvariantCulture)).ConfigureAwait(false);
} }
private async void OnUserPolicyUpdated(object sender, GenericEventArgs<User> e)
{
var dto = _userManager.GetUserDto(e.Argument);
await SendMessageToUserSession(e.Argument, "UserPolicyUpdated", dto).ConfigureAwait(false);
}
private async void OnUserConfigurationUpdated(object sender, GenericEventArgs<User> e)
{
var dto = _userManager.GetUserDto(e.Argument);
await SendMessageToUserSession(e.Argument, "UserConfigurationUpdated", dto).ConfigureAwait(false);
}
private async Task SendMessageToAdminSessions<T>(string name, T data) private async Task SendMessageToAdminSessions<T>(string name, T data)
{ {
try try
@ -175,7 +159,6 @@ namespace Emby.Server.Implementations.EntryPoints
} }
catch (Exception) catch (Exception)
{ {
} }
} }
@ -191,7 +174,6 @@ namespace Emby.Server.Implementations.EntryPoints
} }
catch (Exception) catch (Exception)
{ {
} }
} }
@ -210,10 +192,8 @@ namespace Emby.Server.Implementations.EntryPoints
{ {
if (dispose) if (dispose)
{ {
_userManager.UserDeleted -= OnUserDeleted; _userManager.OnUserDeleted -= OnUserDeleted;
_userManager.UserUpdated -= OnUserUpdated; _userManager.OnUserUpdated -= OnUserUpdated;
_userManager.UserPolicyUpdated -= OnUserPolicyUpdated;
_userManager.UserConfigurationUpdated -= OnUserConfigurationUpdated;
_installationManager.PluginUninstalled -= OnPluginUninstalled; _installationManager.PluginUninstalled -= OnPluginUninstalled;
_installationManager.PackageInstalling -= OnPackageInstalling; _installationManager.PackageInstalling -= OnPackageInstalling;

View File

@ -43,7 +43,6 @@ namespace Emby.Server.Implementations.EntryPoints
_logger = logger; _logger = logger;
_appHost = appHost; _appHost = appHost;
_config = configuration; _config = configuration;
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -580,7 +580,6 @@ namespace Emby.Server.Implementations.HttpServer
} }
catch (NotSupportedException) catch (NotSupportedException)
{ {
} }
} }

View File

@ -1,5 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Text; using System.Text;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;

View File

@ -3,10 +3,11 @@
using System; using System;
using System.Linq; using System.Linq;
using Emby.Server.Implementations.SocketSharp; using Emby.Server.Implementations.SocketSharp;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common.Net; using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.Authentication;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Security;
using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Session;
@ -90,7 +91,8 @@ namespace Emby.Server.Implementations.HttpServer.Security
!string.IsNullOrEmpty(auth.Client) && !string.IsNullOrEmpty(auth.Client) &&
!string.IsNullOrEmpty(auth.Device)) !string.IsNullOrEmpty(auth.Device))
{ {
_sessionManager.LogSessionActivity(auth.Client, _sessionManager.LogSessionActivity(
auth.Client,
auth.Version, auth.Version,
auth.DeviceId, auth.DeviceId,
auth.Device, auth.Device,
@ -104,21 +106,21 @@ namespace Emby.Server.Implementations.HttpServer.Security
private void ValidateUserAccess( private void ValidateUserAccess(
User user, User user,
IRequest request, IRequest request,
IAuthenticationAttributes authAttribtues, IAuthenticationAttributes authAttributes,
AuthorizationInfo auth) AuthorizationInfo auth)
{ {
if (user.Policy.IsDisabled) if (user.HasPermission(PermissionKind.IsDisabled))
{ {
throw new SecurityException("User account has been disabled."); throw new SecurityException("User account has been disabled.");
} }
if (!user.Policy.EnableRemoteAccess && !_networkManager.IsInLocalNetwork(request.RemoteIp)) if (!user.HasPermission(PermissionKind.EnableRemoteAccess) && !_networkManager.IsInLocalNetwork(request.RemoteIp))
{ {
throw new SecurityException("User account has been disabled."); throw new SecurityException("User account has been disabled.");
} }
if (!user.Policy.IsAdministrator if (!user.HasPermission(PermissionKind.IsAdministrator)
&& !authAttribtues.EscapeParentalControl && !authAttributes.EscapeParentalControl
&& !user.IsParentalScheduleAllowed()) && !user.IsParentalScheduleAllowed())
{ {
request.Response.Headers.Add("X-Application-Error-Code", "ParentalControl"); request.Response.Headers.Add("X-Application-Error-Code", "ParentalControl");
@ -180,7 +182,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
{ {
if (roles.Contains("admin", StringComparer.OrdinalIgnoreCase)) if (roles.Contains("admin", StringComparer.OrdinalIgnoreCase))
{ {
if (user == null || !user.Policy.IsAdministrator) if (user == null || !user.HasPermission(PermissionKind.IsAdministrator))
{ {
throw new SecurityException("User does not have admin access."); throw new SecurityException("User does not have admin access.");
} }
@ -188,7 +190,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
if (roles.Contains("delete", StringComparer.OrdinalIgnoreCase)) if (roles.Contains("delete", StringComparer.OrdinalIgnoreCase))
{ {
if (user == null || !user.Policy.EnableContentDeletion) if (user == null || !user.HasPermission(PermissionKind.EnableContentDeletion))
{ {
throw new SecurityException("User does not have delete access."); throw new SecurityException("User does not have delete access.");
} }
@ -196,7 +198,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
if (roles.Contains("download", StringComparer.OrdinalIgnoreCase)) if (roles.Contains("download", StringComparer.OrdinalIgnoreCase))
{ {
if (user == null || !user.Policy.EnableContentDownloading) if (user == null || !user.HasPermission(PermissionKind.EnableContentDownloading))
{ {
throw new SecurityException("User does not have download access."); throw new SecurityException("User does not have download access.");
} }

View File

@ -116,7 +116,6 @@ namespace Emby.Server.Implementations.HttpServer.Security
{ {
info.Device = tokenInfo.DeviceName; info.Device = tokenInfo.DeviceName;
} }
else if (!string.Equals(info.Device, tokenInfo.DeviceName, StringComparison.OrdinalIgnoreCase)) else if (!string.Equals(info.Device, tokenInfo.DeviceName, StringComparison.OrdinalIgnoreCase))
{ {
if (allowTokenInfoUpdate) if (allowTokenInfoUpdate)
@ -149,9 +148,9 @@ namespace Emby.Server.Implementations.HttpServer.Security
{ {
info.User = _userManager.GetUserById(tokenInfo.UserId); info.User = _userManager.GetUserById(tokenInfo.UserId);
if (info.User != null && !string.Equals(info.User.Name, tokenInfo.UserName, StringComparison.OrdinalIgnoreCase)) if (info.User != null && !string.Equals(info.User.Username, tokenInfo.UserName, StringComparison.OrdinalIgnoreCase))
{ {
tokenInfo.UserName = info.User.Name; tokenInfo.UserName = info.User.Username;
updateToken = true; updateToken = true;
} }
} }

View File

@ -1,7 +1,7 @@
#pragma warning disable CS1591 #pragma warning disable CS1591
using System; using System;
using MediaBrowser.Controller.Entities; using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Security;

View File

@ -234,8 +234,10 @@ namespace Emby.Server.Implementations.HttpServer
private Task SendKeepAliveResponse() private Task SendKeepAliveResponse()
{ {
LastKeepAliveDate = DateTime.UtcNow; LastKeepAliveDate = DateTime.UtcNow;
return SendAsync(new WebSocketMessage<string> return SendAsync(
new WebSocketMessage<string>
{ {
MessageId = Guid.NewGuid(),
MessageType = "KeepAlive" MessageType = "KeepAlive"
}, CancellationToken.None); }, CancellationToken.None);
} }

View File

@ -266,7 +266,6 @@ namespace Emby.Server.Implementations.IO
{ {
DisposeWatcher(newWatcher, false); DisposeWatcher(newWatcher, false);
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -393,7 +392,6 @@ namespace Emby.Server.Implementations.IO
} }
return false; return false;
})) }))
{ {
monitorPath = false; monitorPath = false;

View File

@ -71,7 +71,6 @@ namespace Emby.Server.Implementations.Images
new ValueTuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending) new ValueTuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending)
}, },
IncludeItemTypes = includeItemTypes IncludeItemTypes = includeItemTypes
}); });
} }

View File

@ -78,7 +78,6 @@ namespace Emby.Server.Implementations.Images
} }
return i; return i;
}).GroupBy(x => x.Id) }).GroupBy(x => x.Id)
.Select(x => x.First()); .Select(x => x.First());

View File

@ -17,6 +17,8 @@ using Emby.Server.Implementations.Library.Resolvers;
using Emby.Server.Implementations.Library.Validators; using Emby.Server.Implementations.Library.Validators;
using Emby.Server.Implementations.Playlists; using Emby.Server.Implementations.Playlists;
using Emby.Server.Implementations.ScheduledTasks; using Emby.Server.Implementations.ScheduledTasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Progress; using MediaBrowser.Common.Progress;
using MediaBrowser.Controller; using MediaBrowser.Controller;
@ -25,7 +27,6 @@ using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.IO; using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.LiveTv;
@ -46,6 +47,9 @@ using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Tasks; using MediaBrowser.Model.Tasks;
using MediaBrowser.Providers.MediaInfo; using MediaBrowser.Providers.MediaInfo;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
using Genre = MediaBrowser.Controller.Entities.Genre;
using Person = MediaBrowser.Controller.Entities.Person;
using SortOrder = MediaBrowser.Model.Entities.SortOrder; using SortOrder = MediaBrowser.Model.Entities.SortOrder;
using VideoResolver = Emby.Naming.Video.VideoResolver; using VideoResolver = Emby.Naming.Video.VideoResolver;
@ -1539,7 +1543,8 @@ namespace Emby.Server.Implementations.Library
} }
// Handle grouping // Handle grouping
if (user != null && !string.IsNullOrEmpty(view.ViewType) && UserView.IsEligibleForGrouping(view.ViewType) && user.Configuration.GroupedFolders.Length > 0) if (user != null && !string.IsNullOrEmpty(view.ViewType) && UserView.IsEligibleForGrouping(view.ViewType)
&& user.GetPreference(PreferenceKind.GroupedFolders).Length > 0)
{ {
return GetUserRootFolder() return GetUserRootFolder()
.GetChildren(user, true) .GetChildren(user, true)
@ -2856,7 +2861,6 @@ namespace Emby.Server.Implementations.Library
_logger.LogError(ex, "Error getting person"); _logger.LogError(ex, "Error getting person");
return null; return null;
} }
}).Where(i => i != null).ToList(); }).Where(i => i != null).ToList();
} }

View File

@ -148,17 +148,14 @@ namespace Emby.Server.Implementations.Library
{ {
videoStream.BitRate = 30000000; videoStream.BitRate = 30000000;
} }
else if (width >= 1900) else if (width >= 1900)
{ {
videoStream.BitRate = 20000000; videoStream.BitRate = 20000000;
} }
else if (width >= 1200) else if (width >= 1200)
{ {
videoStream.BitRate = 8000000; videoStream.BitRate = 8000000;
} }
else if (width >= 700) else if (width >= 700)
{ {
videoStream.BitRate = 2000000; videoStream.BitRate = 2000000;

View File

@ -7,6 +7,8 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
@ -14,7 +16,6 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Dto; using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
@ -190,10 +191,7 @@ namespace Emby.Server.Implementations.Library
{ {
if (string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase)) if (string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase))
{ {
if (!user.Policy.EnableAudioPlaybackTranscoding) source.SupportsTranscoding = user.HasPermission(PermissionKind.EnableAudioPlaybackTranscoding);
{
source.SupportsTranscoding = false;
}
} }
} }
} }
@ -352,7 +350,9 @@ namespace Emby.Server.Implementations.Library
private void SetDefaultSubtitleStreamIndex(MediaSourceInfo source, UserItemData userData, User user, bool allowRememberingSelection) private void SetDefaultSubtitleStreamIndex(MediaSourceInfo source, UserItemData userData, User user, bool allowRememberingSelection)
{ {
if (userData.SubtitleStreamIndex.HasValue && user.Configuration.RememberSubtitleSelections && user.Configuration.SubtitleMode != SubtitlePlaybackMode.None && allowRememberingSelection) if (userData.SubtitleStreamIndex.HasValue
&& user.RememberSubtitleSelections
&& user.SubtitleMode != SubtitlePlaybackMode.None && allowRememberingSelection)
{ {
var index = userData.SubtitleStreamIndex.Value; var index = userData.SubtitleStreamIndex.Value;
// Make sure the saved index is still valid // Make sure the saved index is still valid
@ -363,26 +363,27 @@ namespace Emby.Server.Implementations.Library
} }
} }
var preferredSubs = string.IsNullOrEmpty(user.Configuration.SubtitleLanguagePreference)
? Array.Empty<string>() : NormalizeLanguage(user.Configuration.SubtitleLanguagePreference); var preferredSubs = string.IsNullOrEmpty(user.SubtitleLanguagePreference)
? Array.Empty<string>() : NormalizeLanguage(user.SubtitleLanguagePreference);
var defaultAudioIndex = source.DefaultAudioStreamIndex; var defaultAudioIndex = source.DefaultAudioStreamIndex;
var audioLangage = defaultAudioIndex == null var audioLangage = defaultAudioIndex == null
? null ? null
: source.MediaStreams.Where(i => i.Type == MediaStreamType.Audio && i.Index == defaultAudioIndex).Select(i => i.Language).FirstOrDefault(); : source.MediaStreams.Where(i => i.Type == MediaStreamType.Audio && i.Index == defaultAudioIndex).Select(i => i.Language).FirstOrDefault();
source.DefaultSubtitleStreamIndex = MediaStreamSelector.GetDefaultSubtitleStreamIndex(source.MediaStreams, source.DefaultSubtitleStreamIndex = MediaStreamSelector.GetDefaultSubtitleStreamIndex(
source.MediaStreams,
preferredSubs, preferredSubs,
user.Configuration.SubtitleMode, user.SubtitleMode,
audioLangage); audioLangage);
MediaStreamSelector.SetSubtitleStreamScores(source.MediaStreams, preferredSubs, MediaStreamSelector.SetSubtitleStreamScores(source.MediaStreams, preferredSubs, user.SubtitleMode, audioLangage);
user.Configuration.SubtitleMode, audioLangage);
} }
private void SetDefaultAudioStreamIndex(MediaSourceInfo source, UserItemData userData, User user, bool allowRememberingSelection) private void SetDefaultAudioStreamIndex(MediaSourceInfo source, UserItemData userData, User user, bool allowRememberingSelection)
{ {
if (userData.AudioStreamIndex.HasValue && user.Configuration.RememberAudioSelections && allowRememberingSelection) if (userData.AudioStreamIndex.HasValue && user.RememberAudioSelections && allowRememberingSelection)
{ {
var index = userData.AudioStreamIndex.Value; var index = userData.AudioStreamIndex.Value;
// Make sure the saved index is still valid // Make sure the saved index is still valid
@ -393,11 +394,11 @@ namespace Emby.Server.Implementations.Library
} }
} }
var preferredAudio = string.IsNullOrEmpty(user.Configuration.AudioLanguagePreference) var preferredAudio = string.IsNullOrEmpty(user.AudioLanguagePreference)
? Array.Empty<string>() ? Array.Empty<string>()
: NormalizeLanguage(user.Configuration.AudioLanguagePreference); : NormalizeLanguage(user.AudioLanguagePreference);
source.DefaultAudioStreamIndex = MediaStreamSelector.GetDefaultAudioStreamIndex(source.MediaStreams, preferredAudio, user.Configuration.PlayDefaultAudioTrack); source.DefaultAudioStreamIndex = MediaStreamSelector.GetDefaultAudioStreamIndex(source.MediaStreams, preferredAudio, user.PlayDefaultAudioTrack);
} }
public void SetDefaultAudioAndSubtitleStreamIndexes(BaseItem item, MediaSourceInfo source, User user) public void SetDefaultAudioAndSubtitleStreamIndexes(BaseItem item, MediaSourceInfo source, User user)
@ -435,7 +436,6 @@ namespace Emby.Server.Implementations.Library
} }
return 1; return 1;
}).ThenBy(i => i.Video3DFormat.HasValue ? 1 : 0) }).ThenBy(i => i.Video3DFormat.HasValue ? 1 : 0)
.ThenByDescending(i => .ThenByDescending(i =>
{ {
@ -534,7 +534,7 @@ namespace Emby.Server.Implementations.Library
mediaSource.RunTimeTicks = null; mediaSource.RunTimeTicks = null;
} }
var audioStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == MediaBrowser.Model.Entities.MediaStreamType.Audio); var audioStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio);
if (audioStream == null || audioStream.Index == -1) if (audioStream == null || audioStream.Index == -1)
{ {
@ -545,7 +545,7 @@ namespace Emby.Server.Implementations.Library
mediaSource.DefaultAudioStreamIndex = audioStream.Index; mediaSource.DefaultAudioStreamIndex = audioStream.Index;
} }
var videoStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == MediaBrowser.Model.Entities.MediaStreamType.Video); var videoStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);
if (videoStream != null) if (videoStream != null)
{ {
if (!videoStream.BitRate.HasValue) if (!videoStream.BitRate.HasValue)
@ -556,17 +556,14 @@ namespace Emby.Server.Implementations.Library
{ {
videoStream.BitRate = 30000000; videoStream.BitRate = 30000000;
} }
else if (width >= 1900) else if (width >= 1900)
{ {
videoStream.BitRate = 20000000; videoStream.BitRate = 20000000;
} }
else if (width >= 1200) else if (width >= 1200)
{ {
videoStream.BitRate = 8000000; videoStream.BitRate = 8000000;
} }
else if (width >= 700) else if (width >= 700)
{ {
videoStream.BitRate = 2000000; videoStream.BitRate = 2000000;
@ -622,7 +619,6 @@ namespace Emby.Server.Implementations.Library
MediaSource = mediaSource, MediaSource = mediaSource,
ExtractChapters = false, ExtractChapters = false,
MediaType = DlnaProfileType.Video MediaType = DlnaProfileType.Video
}, cancellationToken).ConfigureAwait(false); }, cancellationToken).ConfigureAwait(false);
mediaSource.MediaStreams = info.MediaStreams; mediaSource.MediaStreams = info.MediaStreams;
@ -670,13 +666,14 @@ namespace Emby.Server.Implementations.Library
mediaSource.AnalyzeDurationMs = 3000; mediaSource.AnalyzeDurationMs = 3000;
} }
mediaInfo = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest mediaInfo = await _mediaEncoder.GetMediaInfo(
new MediaInfoRequest
{ {
MediaSource = mediaSource, MediaSource = mediaSource,
MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video, MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video,
ExtractChapters = false ExtractChapters = false
},
}, cancellationToken).ConfigureAwait(false); cancellationToken).ConfigureAwait(false);
if (cacheFilePath != null) if (cacheFilePath != null)
{ {
@ -749,17 +746,14 @@ namespace Emby.Server.Implementations.Library
{ {
videoStream.BitRate = 30000000; videoStream.BitRate = 30000000;
} }
else if (width >= 1900) else if (width >= 1900)
{ {
videoStream.BitRate = 20000000; videoStream.BitRate = 20000000;
} }
else if (width >= 1200) else if (width >= 1200)
{ {
videoStream.BitRate = 8000000; videoStream.BitRate = 8000000;
} }
else if (width >= 700) else if (width >= 700)
{ {
videoStream.BitRate = 2000000; videoStream.BitRate = 2000000;

View File

@ -3,7 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using MediaBrowser.Model.Configuration; using Jellyfin.Data.Enums;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
namespace Emby.Server.Implementations.Library namespace Emby.Server.Implementations.Library

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Audio;
@ -10,6 +11,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Playlists; using MediaBrowser.Controller.Playlists;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using MusicAlbum = MediaBrowser.Controller.Entities.Audio.MusicAlbum;
namespace Emby.Server.Implementations.Library namespace Emby.Server.Implementations.Library
{ {
@ -75,7 +77,6 @@ namespace Emby.Server.Implementations.Library
{ {
return Guid.Empty; return Guid.Empty;
} }
}).Where(i => !i.Equals(Guid.Empty)).ToArray(); }).Where(i => !i.Equals(Guid.Empty)).ToArray();
return GetInstantMixFromGenreIds(genreIds, user, dtoOptions); return GetInstantMixFromGenreIds(genreIds, user, dtoOptions);
@ -105,32 +106,27 @@ namespace Emby.Server.Implementations.Library
return GetInstantMixFromGenreIds(new[] { item.Id }, user, dtoOptions); return GetInstantMixFromGenreIds(new[] { item.Id }, user, dtoOptions);
} }
var playlist = item as Playlist; if (item is Playlist playlist)
if (playlist != null)
{ {
return GetInstantMixFromPlaylist(playlist, user, dtoOptions); return GetInstantMixFromPlaylist(playlist, user, dtoOptions);
} }
var album = item as MusicAlbum; if (item is MusicAlbum album)
if (album != null)
{ {
return GetInstantMixFromAlbum(album, user, dtoOptions); return GetInstantMixFromAlbum(album, user, dtoOptions);
} }
var artist = item as MusicArtist; if (item is MusicArtist artist)
if (artist != null)
{ {
return GetInstantMixFromArtist(artist, user, dtoOptions); return GetInstantMixFromArtist(artist, user, dtoOptions);
} }
var song = item as Audio; if (item is Audio song)
if (song != null)
{ {
return GetInstantMixFromSong(song, user, dtoOptions); return GetInstantMixFromSong(song, user, dtoOptions);
} }
var folder = item as Folder; if (item is Folder folder)
if (folder != null)
{ {
return GetInstantMixFromFolder(folder, user, dtoOptions); return GetInstantMixFromFolder(folder, user, dtoOptions);
} }

View File

@ -73,7 +73,6 @@ namespace Emby.Server.Implementations.Library.Resolvers
{ {
return false; return false;
} }
}) })
.Select(i => _fileSystem.GetFileNameWithoutExtension(i)) .Select(i => _fileSystem.GetFileNameWithoutExtension(i))
.FirstOrDefault(); .FirstOrDefault();

View File

@ -94,7 +94,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
_localization.GetLocalizedString("NameSeasonNumber"), _localization.GetLocalizedString("NameSeasonNumber"),
seasonNumber, seasonNumber,
args.GetLibraryOptions().PreferredMetadataLanguage); args.GetLibraryOptions().PreferredMetadataLanguage);
} }
return season; return season;

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Audio;
@ -12,6 +13,8 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Search; using MediaBrowser.Model.Search;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Genre = MediaBrowser.Controller.Entities.Genre;
using Person = MediaBrowser.Controller.Entities.Person;
namespace Emby.Server.Implementations.Library namespace Emby.Server.Implementations.Library
{ {
@ -204,7 +207,6 @@ namespace Emby.Server.Implementations.Library
return mediaItems.Select(i => new SearchHintInfo return mediaItems.Select(i => new SearchHintInfo
{ {
Item = i Item = i
}).ToList(); }).ToList();
} }
} }

View File

@ -5,6 +5,7 @@ using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Threading; using System.Threading;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
@ -13,6 +14,7 @@ using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto; using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Book = MediaBrowser.Controller.Entities.Book;
namespace Emby.Server.Implementations.Library namespace Emby.Server.Implementations.Library
{ {

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,8 @@ using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
@ -17,6 +19,8 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Library; using MediaBrowser.Model.Library;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using Genre = MediaBrowser.Controller.Entities.Genre;
using Person = MediaBrowser.Controller.Entities.Person;
namespace Emby.Server.Implementations.Library namespace Emby.Server.Implementations.Library
{ {
@ -125,12 +129,12 @@ namespace Emby.Server.Implementations.Library
if (!query.IncludeHidden) if (!query.IncludeHidden)
{ {
list = list.Where(i => !user.Configuration.MyMediaExcludes.Contains(i.Id.ToString("N", CultureInfo.InvariantCulture))).ToList(); list = list.Where(i => !user.GetPreference(PreferenceKind.MyMediaExcludes).Contains(i.Id.ToString("N", CultureInfo.InvariantCulture))).ToList();
} }
var sorted = _libraryManager.Sort(list, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).ToList(); var sorted = _libraryManager.Sort(list, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).ToList();
var orders = user.Configuration.OrderedViews.ToList(); var orders = user.GetPreference(PreferenceKind.OrderedViews).ToList();
return list return list
.OrderBy(i => .OrderBy(i =>
@ -165,7 +169,13 @@ namespace Emby.Server.Implementations.Library
return GetUserSubViewWithName(name, parentId, type, sortName); return GetUserSubViewWithName(name, parentId, type, sortName);
} }
private Folder GetUserView(List<ICollectionFolder> parents, string viewType, string localizationKey, string sortName, User user, string[] presetViews) private Folder GetUserView(
List<ICollectionFolder> parents,
string viewType,
string localizationKey,
string sortName,
Jellyfin.Data.Entities.User user,
string[] presetViews)
{ {
if (parents.Count == 1 && parents.All(i => string.Equals(i.CollectionType, viewType, StringComparison.OrdinalIgnoreCase))) if (parents.Count == 1 && parents.All(i => string.Equals(i.CollectionType, viewType, StringComparison.OrdinalIgnoreCase)))
{ {
@ -270,7 +280,8 @@ namespace Emby.Server.Implementations.Library
{ {
parents = _libraryManager.GetUserRootFolder().GetChildren(user, true) parents = _libraryManager.GetUserRootFolder().GetChildren(user, true)
.Where(i => i is Folder) .Where(i => i is Folder)
.Where(i => !user.Configuration.LatestItemsExcludes.Contains(i.Id.ToString("N", CultureInfo.InvariantCulture))) .Where(i => !user.GetPreference(PreferenceKind.LatestItemExcludes)
.Contains(i.Id.ToString("N", CultureInfo.InvariantCulture)))
.ToList(); .ToList();
} }
@ -331,12 +342,11 @@ namespace Emby.Server.Implementations.Library
var excludeItemTypes = includeItemTypes.Length == 0 && mediaTypes.Count == 0 ? new[] var excludeItemTypes = includeItemTypes.Length == 0 && mediaTypes.Count == 0 ? new[]
{ {
typeof(Person).Name, nameof(Person),
typeof(Studio).Name, nameof(Studio),
typeof(Year).Name, nameof(Year),
typeof(MusicGenre).Name, nameof(MusicGenre),
typeof(Genre).Name nameof(Genre)
} : Array.Empty<string>(); } : Array.Empty<string>();
var query = new InternalItemsQuery(user) var query = new InternalItemsQuery(user)

View File

@ -98,7 +98,6 @@ namespace Emby.Server.Implementations.Library.Validators
_libraryManager.DeleteItem(item, new DeleteOptions _libraryManager.DeleteItem(item, new DeleteOptions
{ {
DeleteFileLocation = false DeleteFileLocation = false
}, false); }, false);
} }

View File

@ -92,7 +92,6 @@ namespace Emby.Server.Implementations.Library.Validators
_libraryManager.DeleteItem(item, new DeleteOptions _libraryManager.DeleteItem(item, new DeleteOptions
{ {
DeleteFileLocation = false DeleteFileLocation = false
}, false); }, false);
} }

View File

@ -1547,7 +1547,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
IsFolder = false, IsFolder = false,
Recursive = true, Recursive = true,
DtoOptions = new DtoOptions(true) DtoOptions = new DtoOptions(true)
}) })
.Where(i => i.IsFileProtocol && File.Exists(i.Path)) .Where(i => i.IsFileProtocol && File.Exists(i.Path))
.Skip(seriesTimer.KeepUpTo - 1) .Skip(seriesTimer.KeepUpTo - 1)

View File

@ -56,7 +56,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
name += " " + info.EpisodeTitle; name += " " + info.EpisodeTitle;
} }
} }
else if (info.IsMovie && info.ProductionYear != null) else if (info.IsMovie && info.ProductionYear != null)
{ {
name += " (" + info.ProductionYear + ")"; name += " (" + info.ProductionYear + ")";

View File

@ -1218,7 +1218,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings
public string programID { get; set; } public string programID { get; set; }
public List<ImageData> data { get; set; } public List<ImageData> data { get; set; }
} }
} }
} }
} }

View File

@ -7,6 +7,8 @@ using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Emby.Server.Implementations.Library; using Emby.Server.Implementations.Library;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Progress; using MediaBrowser.Common.Progress;
@ -14,8 +16,6 @@ using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Persistence;
@ -31,6 +31,8 @@ using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Tasks; using MediaBrowser.Model.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
using Movie = MediaBrowser.Controller.Entities.Movies.Movie;
namespace Emby.Server.Implementations.LiveTv namespace Emby.Server.Implementations.LiveTv
{ {
@ -696,7 +698,6 @@ namespace Emby.Server.Implementations.LiveTv
{ {
Path = info.ThumbImageUrl, Path = info.ThumbImageUrl,
Type = ImageType.Thumb Type = ImageType.Thumb
}, 0); }, 0);
} }
} }
@ -709,7 +710,6 @@ namespace Emby.Server.Implementations.LiveTv
{ {
Path = info.LogoImageUrl, Path = info.LogoImageUrl,
Type = ImageType.Logo Type = ImageType.Logo
}, 0); }, 0);
} }
} }
@ -722,7 +722,6 @@ namespace Emby.Server.Implementations.LiveTv
{ {
Path = info.BackdropImageUrl, Path = info.BackdropImageUrl,
Type = ImageType.Backdrop Type = ImageType.Backdrop
}, 0); }, 0);
} }
} }
@ -760,7 +759,8 @@ namespace Emby.Server.Implementations.LiveTv
var dto = _dtoService.GetBaseItemDto(program, new DtoOptions(), user); var dto = _dtoService.GetBaseItemDto(program, new DtoOptions(), user);
var list = new List<Tuple<BaseItemDto, string, string>>() { var list = new List<Tuple<BaseItemDto, string, string>>
{
new Tuple<BaseItemDto, string, string>(dto, program.ExternalId, program.ExternalSeriesId) new Tuple<BaseItemDto, string, string>(dto, program.ExternalId, program.ExternalSeriesId)
}; };
@ -1168,7 +1168,6 @@ namespace Emby.Server.Implementations.LiveTv
IncludeItemTypes = new string[] { typeof(LiveTvProgram).Name }, IncludeItemTypes = new string[] { typeof(LiveTvProgram).Name },
ChannelIds = new Guid[] { currentChannel.Id }, ChannelIds = new Guid[] { currentChannel.Id },
DtoOptions = new DtoOptions(true) DtoOptions = new DtoOptions(true)
}).Cast<LiveTvProgram>().ToDictionary(i => i.Id); }).Cast<LiveTvProgram>().ToDictionary(i => i.Id);
var newPrograms = new List<LiveTvProgram>(); var newPrograms = new List<LiveTvProgram>();
@ -1738,7 +1737,6 @@ namespace Emby.Server.Implementations.LiveTv
var results = await GetTimers(new TimerQuery var results = await GetTimers(new TimerQuery
{ {
Id = id Id = id
}, cancellationToken).ConfigureAwait(false); }, cancellationToken).ConfigureAwait(false);
return results.Items.FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.OrdinalIgnoreCase)); return results.Items.FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.OrdinalIgnoreCase));
@ -1790,7 +1788,6 @@ namespace Emby.Server.Implementations.LiveTv
.Select(i => .Select(i =>
{ {
return i.Item1; return i.Item1;
}) })
.ToArray(); .ToArray();
@ -1845,7 +1842,6 @@ namespace Emby.Server.Implementations.LiveTv
} }
return _tvDtoService.GetSeriesTimerInfoDto(i.Item1, i.Item2, channelName); return _tvDtoService.GetSeriesTimerInfoDto(i.Item1, i.Item2, channelName);
}) })
.ToArray(); .ToArray();
@ -1878,7 +1874,6 @@ namespace Emby.Server.Implementations.LiveTv
OrderBy = new[] { (ItemSortBy.StartDate, SortOrder.Ascending) }, OrderBy = new[] { (ItemSortBy.StartDate, SortOrder.Ascending) },
TopParentIds = new[] { GetInternalLiveTvFolder(CancellationToken.None).Id }, TopParentIds = new[] { GetInternalLiveTvFolder(CancellationToken.None).Id },
DtoOptions = options DtoOptions = options
}) : new List<BaseItem>(); }) : new List<BaseItem>();
RemoveFields(options); RemoveFields(options);
@ -2167,20 +2162,19 @@ namespace Emby.Server.Implementations.LiveTv
var info = new LiveTvInfo var info = new LiveTvInfo
{ {
Services = services, Services = services,
IsEnabled = services.Length > 0 IsEnabled = services.Length > 0,
}; EnabledUsers = _userManager.Users
info.EnabledUsers = _userManager.Users
.Where(IsLiveTvEnabled) .Where(IsLiveTvEnabled)
.Select(i => i.Id.ToString("N", CultureInfo.InvariantCulture)) .Select(i => i.Id.ToString("N", CultureInfo.InvariantCulture))
.ToArray(); .ToArray()
};
return info; return info;
} }
private bool IsLiveTvEnabled(User user) private bool IsLiveTvEnabled(User user)
{ {
return user.Policy.EnableLiveTvAccess && (Services.Count > 1 || GetConfiguration().TunerHosts.Length > 0); return user.HasPermission(PermissionKind.EnableLiveTvAccess) && (Services.Count > 1 || GetConfiguration().TunerHosts.Length > 0);
} }
public IEnumerable<User> GetEnabledUsers() public IEnumerable<User> GetEnabledUsers()
@ -2457,7 +2451,6 @@ namespace Emby.Server.Implementations.LiveTv
UserId = user.Id, UserId = user.Id,
IsRecordingsFolder = true, IsRecordingsFolder = true,
RefreshLatestChannelItems = refreshChannels RefreshLatestChannelItems = refreshChannels
}).Items); }).Items);
return folders.Cast<BaseItem>().ToList(); return folders.Cast<BaseItem>().ToList();

View File

@ -99,7 +99,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
} }
catch (IOException) catch (IOException)
{ {
} }
} }
} }
@ -116,7 +115,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
} }
catch (IOException) catch (IOException)
{ {
} }
} }
} }

View File

@ -111,7 +111,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
ChannelType = ChannelType.TV, ChannelType = ChannelType.TV,
IsLegacyTuner = (i.URL ?? string.Empty).StartsWith("hdhomerun", StringComparison.OrdinalIgnoreCase), IsLegacyTuner = (i.URL ?? string.Empty).StartsWith("hdhomerun", StringComparison.OrdinalIgnoreCase),
Path = i.URL Path = i.URL
}).Cast<ChannelInfo>().ToList(); }).Cast<ChannelInfo>().ToList();
} }
@ -481,7 +480,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
Height = height, Height = height,
BitRate = videoBitrate, BitRate = videoBitrate,
NalLengthSize = nal NalLengthSize = nal
}, },
new MediaStream new MediaStream
{ {
@ -722,7 +720,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
} }
} }
} }
} }
catch (OperationCanceledException) catch (OperationCanceledException)
{ {

View File

@ -220,11 +220,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
} }
catch (IOException) catch (IOException)
{ {
} }
catch (ArgumentException) catch (ArgumentException)
{ {
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@ -127,7 +127,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
{ {
using (var stream = await new M3uParser(Logger, _httpClient, _appHost).GetListingsStream(info.Url, CancellationToken.None).ConfigureAwait(false)) using (var stream = await new M3uParser(Logger, _httpClient, _appHost).GetListingsStream(info.Url, CancellationToken.None).ConfigureAwait(false))
{ {
} }
} }

View File

@ -210,7 +210,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
} }
} }
} }
} }
if (!IsValidChannelNumber(numberString)) if (!IsValidChannelNumber(numberString))

View File

@ -98,7 +98,6 @@ namespace Emby.Server.Implementations.Net
} }
catch (SocketException) catch (SocketException)
{ {
} }
try try
@ -109,7 +108,6 @@ namespace Emby.Server.Implementations.Net
} }
catch (SocketException) catch (SocketException)
{ {
} }
try try

View File

@ -3,6 +3,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Playlists; using MediaBrowser.Controller.Playlists;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
@ -44,7 +45,7 @@ namespace Emby.Server.Implementations.Playlists
} }
query.Recursive = true; query.Recursive = true;
query.IncludeItemTypes = new string[] { "Playlist" }; query.IncludeItemTypes = new[] { "Playlist" };
query.Parent = null; query.Parent = null;
return LibraryManager.GetItemsResult(query); return LibraryManager.GetItemsResult(query);
} }

View File

@ -7,6 +7,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Audio;
@ -21,6 +22,8 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using PlaylistsNET.Content; using PlaylistsNET.Content;
using PlaylistsNET.Models; using PlaylistsNET.Models;
using Genre = MediaBrowser.Controller.Entities.Genre;
using MusicAlbum = MediaBrowser.Controller.Entities.Audio.MusicAlbum;
namespace Emby.Server.Implementations.Playlists namespace Emby.Server.Implementations.Playlists
{ {

View File

@ -61,7 +61,6 @@ namespace Emby.Server.Implementations.Security
AddColumn(db, "AccessTokens", "UserName", "TEXT", existingColumnNames); AddColumn(db, "AccessTokens", "UserName", "TEXT", existingColumnNames);
AddColumn(db, "AccessTokens", "DateLastActivity", "DATETIME", existingColumnNames); AddColumn(db, "AccessTokens", "DateLastActivity", "DATETIME", existingColumnNames);
AddColumn(db, "AccessTokens", "AppVersion", "TEXT", existingColumnNames); AddColumn(db, "AccessTokens", "AppVersion", "TEXT", existingColumnNames);
}, TransactionMode); }, TransactionMode);
connection.RunQueries(new[] connection.RunQueries(new[]
@ -107,7 +106,6 @@ namespace Emby.Server.Implementations.Security
statement.MoveNext(); statement.MoveNext();
} }
}, TransactionMode); }, TransactionMode);
} }
} }
@ -367,7 +365,6 @@ namespace Emby.Server.Implementations.Security
return result; return result;
} }
}, ReadTransactionMode); }, ReadTransactionMode);
} }
} }
@ -398,7 +395,6 @@ namespace Emby.Server.Implementations.Security
statement.MoveNext(); statement.MoveNext();
} }
}, TransactionMode); }, TransactionMode);
} }
} }

View File

@ -7,6 +7,8 @@ using System.Globalization;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common.Events; using MediaBrowser.Common.Events;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller; using MediaBrowser.Controller;
@ -15,7 +17,6 @@ using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Security;
@ -28,7 +29,9 @@ using MediaBrowser.Model.Library;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Session; using MediaBrowser.Model.Session;
using MediaBrowser.Model.SyncPlay; using MediaBrowser.Model.SyncPlay;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
namespace Emby.Server.Implementations.Session namespace Emby.Server.Implementations.Session
{ {
@ -283,12 +286,19 @@ namespace Emby.Server.Implementations.Session
if (user != null) if (user != null)
{ {
var userLastActivityDate = user.LastActivityDate ?? DateTime.MinValue; var userLastActivityDate = user.LastActivityDate ?? DateTime.MinValue;
user.LastActivityDate = activityDate;
if ((activityDate - userLastActivityDate).TotalSeconds > 60) if ((activityDate - userLastActivityDate).TotalSeconds > 60)
{ {
try
{
user.LastActivityDate = activityDate;
_userManager.UpdateUser(user); _userManager.UpdateUser(user);
} }
catch (DbUpdateConcurrencyException e)
{
_logger.LogWarning(e, "Error updating user's last activity date.");
}
}
} }
if ((activityDate - lastActivityDate).TotalSeconds > 10) if ((activityDate - lastActivityDate).TotalSeconds > 10)
@ -434,7 +444,13 @@ namespace Emby.Server.Implementations.Session
/// <param name="remoteEndPoint">The remote end point.</param> /// <param name="remoteEndPoint">The remote end point.</param>
/// <param name="user">The user.</param> /// <param name="user">The user.</param>
/// <returns>SessionInfo.</returns> /// <returns>SessionInfo.</returns>
private SessionInfo GetSessionInfo(string appName, string appVersion, string deviceId, string deviceName, string remoteEndPoint, User user) private SessionInfo GetSessionInfo(
string appName,
string appVersion,
string deviceId,
string deviceName,
string remoteEndPoint,
User user)
{ {
CheckDisposed(); CheckDisposed();
@ -447,14 +463,13 @@ namespace Emby.Server.Implementations.Session
CheckDisposed(); CheckDisposed();
var sessionInfo = _activeConnections.GetOrAdd(key, k => var sessionInfo = _activeConnections.GetOrAdd(
{ key,
return CreateSession(k, appName, appVersion, deviceId, deviceName, remoteEndPoint, user); k => CreateSession(k, appName, appVersion, deviceId, deviceName, remoteEndPoint, user));
});
sessionInfo.UserId = user == null ? Guid.Empty : user.Id; sessionInfo.UserId = user?.Id ?? Guid.Empty;
sessionInfo.UserName = user?.Name; sessionInfo.UserName = user?.Username;
sessionInfo.UserPrimaryImageTag = user == null ? null : GetImageCacheTag(user, ImageType.Primary); sessionInfo.UserPrimaryImageTag = user?.ProfileImage == null ? null : GetImageCacheTag(user);
sessionInfo.RemoteEndPoint = remoteEndPoint; sessionInfo.RemoteEndPoint = remoteEndPoint;
sessionInfo.Client = appName; sessionInfo.Client = appName;
@ -473,7 +488,14 @@ namespace Emby.Server.Implementations.Session
return sessionInfo; return sessionInfo;
} }
private SessionInfo CreateSession(string key, string appName, string appVersion, string deviceId, string deviceName, string remoteEndPoint, User user) private SessionInfo CreateSession(
string key,
string appName,
string appVersion,
string deviceId,
string deviceName,
string remoteEndPoint,
User user)
{ {
var sessionInfo = new SessionInfo(this, _logger) var sessionInfo = new SessionInfo(this, _logger)
{ {
@ -483,11 +505,11 @@ namespace Emby.Server.Implementations.Session
Id = key.GetMD5().ToString("N", CultureInfo.InvariantCulture) Id = key.GetMD5().ToString("N", CultureInfo.InvariantCulture)
}; };
var username = user?.Name; var username = user?.Username;
sessionInfo.UserId = user?.Id ?? Guid.Empty; sessionInfo.UserId = user?.Id ?? Guid.Empty;
sessionInfo.UserName = username; sessionInfo.UserName = username;
sessionInfo.UserPrimaryImageTag = user == null ? null : GetImageCacheTag(user, ImageType.Primary); sessionInfo.UserPrimaryImageTag = user?.ProfileImage == null ? null : GetImageCacheTag(user);
sessionInfo.RemoteEndPoint = remoteEndPoint; sessionInfo.RemoteEndPoint = remoteEndPoint;
if (string.IsNullOrEmpty(deviceName)) if (string.IsNullOrEmpty(deviceName))
@ -535,10 +557,7 @@ namespace Emby.Server.Implementations.Session
private void StartIdleCheckTimer() private void StartIdleCheckTimer()
{ {
if (_idleTimer == null) _idleTimer ??= new Timer(CheckForIdlePlayback, null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
{
_idleTimer = new Timer(CheckForIdlePlayback, null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
}
} }
private void StopIdleCheckTimer() private void StopIdleCheckTimer()
@ -786,7 +805,7 @@ namespace Emby.Server.Implementations.Session
{ {
var changed = false; var changed = false;
if (user.Configuration.RememberAudioSelections) if (user.RememberAudioSelections)
{ {
if (data.AudioStreamIndex != info.AudioStreamIndex) if (data.AudioStreamIndex != info.AudioStreamIndex)
{ {
@ -803,7 +822,7 @@ namespace Emby.Server.Implementations.Session
} }
} }
if (user.Configuration.RememberSubtitleSelections) if (user.RememberSubtitleSelections)
{ {
if (data.SubtitleStreamIndex != info.SubtitleStreamIndex) if (data.SubtitleStreamIndex != info.SubtitleStreamIndex)
{ {
@ -1114,13 +1133,13 @@ namespace Emby.Server.Implementations.Session
if (items.Any(i => i.GetPlayAccess(user) != PlayAccess.Full)) if (items.Any(i => i.GetPlayAccess(user) != PlayAccess.Full))
{ {
throw new ArgumentException( throw new ArgumentException(
string.Format(CultureInfo.InvariantCulture, "{0} is not allowed to play media.", user.Name)); string.Format(CultureInfo.InvariantCulture, "{0} is not allowed to play media.", user.Username));
} }
} }
if (user != null if (user != null
&& command.ItemIds.Length == 1 && command.ItemIds.Length == 1
&& user.Configuration.EnableNextEpisodeAutoPlay && user.EnableNextEpisodeAutoPlay
&& _libraryManager.GetItemById(command.ItemIds[0]) is Episode episode) && _libraryManager.GetItemById(command.ItemIds[0]) is Episode episode)
{ {
var series = episode.Series; var series = episode.Series;
@ -1191,7 +1210,7 @@ namespace Emby.Server.Implementations.Session
DtoOptions = new DtoOptions(false) DtoOptions = new DtoOptions(false)
{ {
EnableImages = false, EnableImages = false,
Fields = new ItemFields[] Fields = new[]
{ {
ItemFields.SortName ItemFields.SortName
} }
@ -1353,7 +1372,7 @@ namespace Emby.Server.Implementations.Session
list.Add(new SessionUserInfo list.Add(new SessionUserInfo
{ {
UserId = userId, UserId = userId,
UserName = user.Name UserName = user.Username
}); });
session.AdditionalUsers = list.ToArray(); session.AdditionalUsers = list.ToArray();
@ -1513,7 +1532,7 @@ namespace Emby.Server.Implementations.Session
DeviceName = deviceName, DeviceName = deviceName,
UserId = user.Id, UserId = user.Id,
AccessToken = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture), AccessToken = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture),
UserName = user.Name UserName = user.Username
}; };
_logger.LogInformation("Creating new access token for user {0}", user.Id); _logger.LogInformation("Creating new access token for user {0}", user.Id);
@ -1710,15 +1729,15 @@ namespace Emby.Server.Implementations.Session
return info; return info;
} }
private string GetImageCacheTag(BaseItem item, ImageType type) private string GetImageCacheTag(User user)
{ {
try try
{ {
return _imageProcessor.GetImageCacheTag(item, type); return _imageProcessor.GetImageCacheTag(user);
} }
catch (Exception ex) catch (Exception e)
{ {
_logger.LogError(ex, "Error getting image information for {Type}", type); _logger.LogError(e, "Error getting image information for profile image");
return null; return null;
} }
} }
@ -1827,7 +1846,10 @@ namespace Emby.Server.Implementations.Session
{ {
CheckDisposed(); CheckDisposed();
var adminUserIds = _userManager.Users.Where(i => i.Policy.IsAdministrator).Select(i => i.Id).ToList(); var adminUserIds = _userManager.Users
.Where(i => i.HasPermission(PermissionKind.IsAdministrator))
.Select(i => i.Id)
.ToList();
return SendMessageToUserSessions(adminUserIds, name, data, cancellationToken); return SendMessageToUserSessions(adminUserIds, name, data, cancellationToken);
} }

View File

@ -1,6 +1,7 @@
#pragma warning disable CS1591 #pragma warning disable CS1591
using System; using System;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Sorting; using MediaBrowser.Controller.Sorting;

View File

@ -1,4 +1,5 @@
using System; using System;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Sorting; using MediaBrowser.Controller.Sorting;

View File

@ -1,5 +1,6 @@
#pragma warning disable CS1591 #pragma warning disable CS1591
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Sorting; using MediaBrowser.Controller.Sorting;

View File

@ -1,5 +1,6 @@
#pragma warning disable CS1591 #pragma warning disable CS1591
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Sorting; using MediaBrowser.Controller.Sorting;

View File

@ -1,5 +1,6 @@
#pragma warning disable CS1591 #pragma warning disable CS1591
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Sorting; using MediaBrowser.Controller.Sorting;

View File

@ -1,3 +1,4 @@
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Sorting; using MediaBrowser.Controller.Sorting;

View File

@ -102,20 +102,15 @@ namespace Emby.Server.Implementations.SyncPlay
return new SessionInfo[] { from }; return new SessionInfo[] { from };
case BroadcastType.AllGroup: case BroadcastType.AllGroup:
return _group.Participants.Values.Select( return _group.Participants.Values.Select(
session => session.Session session => session.Session).ToArray();
).ToArray();
case BroadcastType.AllExceptCurrentSession: case BroadcastType.AllExceptCurrentSession:
return _group.Participants.Values.Select( return _group.Participants.Values.Select(
session => session.Session session => session.Session).Where(
).Where( session => !session.Id.Equals(from.Id)).ToArray();
session => !session.Id.Equals(from.Id)
).ToArray();
case BroadcastType.AllReady: case BroadcastType.AllReady:
return _group.Participants.Values.Where( return _group.Participants.Values.Where(
session => !session.IsBuffering session => !session.IsBuffering).Select(
).Select( session => session.Session).ToArray();
session => session.Session
).ToArray();
default: default:
return Array.Empty<SessionInfo>(); return Array.Empty<SessionInfo>();
} }
@ -314,8 +309,7 @@ namespace Emby.Server.Implementations.SyncPlay
// Playback synchronization will mainly happen client side // Playback synchronization will mainly happen client side
_group.IsPaused = false; _group.IsPaused = false;
_group.LastActivity = DateTime.UtcNow.AddMilliseconds( _group.LastActivity = DateTime.UtcNow.AddMilliseconds(
delay delay);
);
var command = NewSyncPlayCommand(SendCommandType.Play); var command = NewSyncPlayCommand(SendCommandType.Play);
SendCommand(session, BroadcastType.AllGroup, command, cancellationToken); SendCommand(session, BroadcastType.AllGroup, command, cancellationToken);
@ -449,8 +443,7 @@ namespace Emby.Server.Implementations.SyncPlay
{ {
// Client that was buffering is recovering, notifying others to resume // Client that was buffering is recovering, notifying others to resume
_group.LastActivity = currentTime.AddMilliseconds( _group.LastActivity = currentTime.AddMilliseconds(
delay delay);
);
var command = NewSyncPlayCommand(SendCommandType.Play); var command = NewSyncPlayCommand(SendCommandType.Play);
SendCommand(session, BroadcastType.AllExceptCurrentSession, command, cancellationToken); SendCommand(session, BroadcastType.AllExceptCurrentSession, command, cancellationToken);
} }
@ -461,8 +454,7 @@ namespace Emby.Server.Implementations.SyncPlay
delay = delay < _group.DefaulPing ? _group.DefaulPing : delay; delay = delay < _group.DefaulPing ? _group.DefaulPing : delay;
_group.LastActivity = currentTime.AddMilliseconds( _group.LastActivity = currentTime.AddMilliseconds(
delay delay);
);
var command = NewSyncPlayCommand(SendCommandType.Play); var command = NewSyncPlayCommand(SendCommandType.Play);
SendCommand(session, BroadcastType.AllGroup, command, cancellationToken); SendCommand(session, BroadcastType.AllGroup, command, cancellationToken);

View File

@ -3,13 +3,13 @@ using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using Microsoft.Extensions.Logging; using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Entities; using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Session;
using MediaBrowser.Controller.SyncPlay; using MediaBrowser.Controller.SyncPlay;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.SyncPlay; using MediaBrowser.Model.SyncPlay;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.SyncPlay namespace Emby.Server.Implementations.SyncPlay
{ {
@ -109,14 +109,6 @@ namespace Emby.Server.Implementations.SyncPlay
_disposed = true; _disposed = true;
} }
private void CheckDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(GetType().Name);
}
}
private void OnSessionManagerSessionEnded(object sender, SessionEventArgs e) private void OnSessionManagerSessionEnded(object sender, SessionEventArgs e)
{ {
var session = e.SessionInfo; var session = e.SessionInfo;
@ -149,38 +141,24 @@ namespace Emby.Server.Implementations.SyncPlay
var item = _libraryManager.GetItemById(itemId); var item = _libraryManager.GetItemById(itemId);
// Check ParentalRating access // Check ParentalRating access
var hasParentalRatingAccess = true; var hasParentalRatingAccess = !user.MaxParentalAgeRating.HasValue
if (user.Policy.MaxParentalRating.HasValue) || item.InheritedParentalRatingValue <= user.MaxParentalAgeRating;
{
hasParentalRatingAccess = item.InheritedParentalRatingValue <= user.Policy.MaxParentalRating;
}
if (!user.Policy.EnableAllFolders && hasParentalRatingAccess) if (!user.HasPermission(PermissionKind.EnableAllFolders) && hasParentalRatingAccess)
{ {
var collections = _libraryManager.GetCollectionFolders(item).Select( var collections = _libraryManager.GetCollectionFolders(item).Select(
folder => folder.Id.ToString("N", CultureInfo.InvariantCulture) folder => folder.Id.ToString("N", CultureInfo.InvariantCulture));
);
var intersect = collections.Intersect(user.Policy.EnabledFolders); return collections.Intersect(user.GetPreference(PreferenceKind.EnabledFolders)).Any();
return intersect.Any();
} }
else
{
return hasParentalRatingAccess; return hasParentalRatingAccess;
} }
}
private Guid? GetSessionGroup(SessionInfo session) private Guid? GetSessionGroup(SessionInfo session)
{ {
ISyncPlayController group; _sessionToGroupMap.TryGetValue(session.Id, out var group);
_sessionToGroupMap.TryGetValue(session.Id, out group); return group?.GetGroupId();
if (group != null)
{
return group.GetGroupId();
}
else
{
return null;
}
} }
/// <inheritdoc /> /// <inheritdoc />
@ -188,7 +166,7 @@ namespace Emby.Server.Implementations.SyncPlay
{ {
var user = _userManager.GetUserById(session.UserId); var user = _userManager.GetUserById(session.UserId);
if (user.Policy.SyncPlayAccess != SyncPlayAccess.CreateAndJoinGroups) if (user.SyncPlayAccess != SyncPlayAccess.CreateAndJoinGroups)
{ {
_logger.LogWarning("NewGroup: {0} does not have permission to create groups.", session.Id); _logger.LogWarning("NewGroup: {0} does not have permission to create groups.", session.Id);
@ -196,7 +174,7 @@ namespace Emby.Server.Implementations.SyncPlay
{ {
Type = GroupUpdateType.CreateGroupDenied Type = GroupUpdateType.CreateGroupDenied
}; };
_sessionManager.SendSyncPlayGroupUpdate(session.Id.ToString(), error, CancellationToken.None); _sessionManager.SendSyncPlayGroupUpdate(session.Id, error, CancellationToken.None);
return; return;
} }
@ -219,7 +197,7 @@ namespace Emby.Server.Implementations.SyncPlay
{ {
var user = _userManager.GetUserById(session.UserId); var user = _userManager.GetUserById(session.UserId);
if (user.Policy.SyncPlayAccess == SyncPlayAccess.None) if (user.SyncPlayAccess == SyncPlayAccess.None)
{ {
_logger.LogWarning("JoinGroup: {0} does not have access to SyncPlay.", session.Id); _logger.LogWarning("JoinGroup: {0} does not have access to SyncPlay.", session.Id);
@ -227,7 +205,7 @@ namespace Emby.Server.Implementations.SyncPlay
{ {
Type = GroupUpdateType.JoinGroupDenied Type = GroupUpdateType.JoinGroupDenied
}; };
_sessionManager.SendSyncPlayGroupUpdate(session.Id.ToString(), error, CancellationToken.None); _sessionManager.SendSyncPlayGroupUpdate(session.Id, error, CancellationToken.None);
return; return;
} }
@ -244,7 +222,7 @@ namespace Emby.Server.Implementations.SyncPlay
{ {
Type = GroupUpdateType.GroupDoesNotExist Type = GroupUpdateType.GroupDoesNotExist
}; };
_sessionManager.SendSyncPlayGroupUpdate(session.Id.ToString(), error, CancellationToken.None); _sessionManager.SendSyncPlayGroupUpdate(session.Id, error, CancellationToken.None);
return; return;
} }
@ -257,7 +235,7 @@ namespace Emby.Server.Implementations.SyncPlay
GroupId = group.GetGroupId().ToString(), GroupId = group.GetGroupId().ToString(),
Type = GroupUpdateType.LibraryAccessDenied Type = GroupUpdateType.LibraryAccessDenied
}; };
_sessionManager.SendSyncPlayGroupUpdate(session.Id.ToString(), error, CancellationToken.None); _sessionManager.SendSyncPlayGroupUpdate(session.Id, error, CancellationToken.None);
return; return;
} }
@ -281,8 +259,7 @@ namespace Emby.Server.Implementations.SyncPlay
// TODO: determine what happens to users that are in a group and get their permissions revoked // TODO: determine what happens to users that are in a group and get their permissions revoked
lock (_groupsLock) lock (_groupsLock)
{ {
ISyncPlayController group; _sessionToGroupMap.TryGetValue(session.Id, out var group);
_sessionToGroupMap.TryGetValue(session.Id, out group);
if (group == null) if (group == null)
{ {
@ -292,7 +269,7 @@ namespace Emby.Server.Implementations.SyncPlay
{ {
Type = GroupUpdateType.NotInGroup Type = GroupUpdateType.NotInGroup
}; };
_sessionManager.SendSyncPlayGroupUpdate(session.Id.ToString(), error, CancellationToken.None); _sessionManager.SendSyncPlayGroupUpdate(session.Id, error, CancellationToken.None);
return; return;
} }
@ -311,7 +288,7 @@ namespace Emby.Server.Implementations.SyncPlay
{ {
var user = _userManager.GetUserById(session.UserId); var user = _userManager.GetUserById(session.UserId);
if (user.Policy.SyncPlayAccess == SyncPlayAccess.None) if (user.SyncPlayAccess == SyncPlayAccess.None)
{ {
return new List<GroupInfoView>(); return new List<GroupInfoView>();
} }
@ -320,19 +297,15 @@ namespace Emby.Server.Implementations.SyncPlay
if (!filterItemId.Equals(Guid.Empty)) if (!filterItemId.Equals(Guid.Empty))
{ {
return _groups.Values.Where( return _groups.Values.Where(
group => group.GetPlayingItemId().Equals(filterItemId) && HasAccessToItem(user, group.GetPlayingItemId()) group => group.GetPlayingItemId().Equals(filterItemId) && HasAccessToItem(user, group.GetPlayingItemId())).Select(
).Select( group => group.GetInfo()).ToList();
group => group.GetInfo()
).ToList();
} }
// Otherwise show all available groups // Otherwise show all available groups
else else
{ {
return _groups.Values.Where( return _groups.Values.Where(
group => HasAccessToItem(user, group.GetPlayingItemId()) group => HasAccessToItem(user, group.GetPlayingItemId())).Select(
).Select( group => group.GetInfo()).ToList();
group => group.GetInfo()
).ToList();
} }
} }
@ -341,7 +314,7 @@ namespace Emby.Server.Implementations.SyncPlay
{ {
var user = _userManager.GetUserById(session.UserId); var user = _userManager.GetUserById(session.UserId);
if (user.Policy.SyncPlayAccess == SyncPlayAccess.None) if (user.SyncPlayAccess == SyncPlayAccess.None)
{ {
_logger.LogWarning("HandleRequest: {0} does not have access to SyncPlay.", session.Id); _logger.LogWarning("HandleRequest: {0} does not have access to SyncPlay.", session.Id);
@ -349,14 +322,13 @@ namespace Emby.Server.Implementations.SyncPlay
{ {
Type = GroupUpdateType.JoinGroupDenied Type = GroupUpdateType.JoinGroupDenied
}; };
_sessionManager.SendSyncPlayGroupUpdate(session.Id.ToString(), error, CancellationToken.None); _sessionManager.SendSyncPlayGroupUpdate(session.Id, error, CancellationToken.None);
return; return;
} }
lock (_groupsLock) lock (_groupsLock)
{ {
ISyncPlayController group; _sessionToGroupMap.TryGetValue(session.Id, out var group);
_sessionToGroupMap.TryGetValue(session.Id, out group);
if (group == null) if (group == null)
{ {
@ -366,7 +338,7 @@ namespace Emby.Server.Implementations.SyncPlay
{ {
Type = GroupUpdateType.NotInGroup Type = GroupUpdateType.NotInGroup
}; };
_sessionManager.SendSyncPlayGroupUpdate(session.Id.ToString(), error, CancellationToken.None); _sessionManager.SendSyncPlayGroupUpdate(session.Id, error, CancellationToken.None);
return; return;
} }
@ -393,8 +365,7 @@ namespace Emby.Server.Implementations.SyncPlay
throw new InvalidOperationException("Session not in any group!"); throw new InvalidOperationException("Session not in any group!");
} }
ISyncPlayController tempGroup; _sessionToGroupMap.Remove(session.Id, out var tempGroup);
_sessionToGroupMap.Remove(session.Id, out tempGroup);
if (!tempGroup.GetGroupId().Equals(group.GetGroupId())) if (!tempGroup.GetGroupId().Equals(group.GetGroupId()))
{ {

View File

@ -4,13 +4,17 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.TV; using MediaBrowser.Controller.TV;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
using Series = MediaBrowser.Controller.Entities.TV.Series;
namespace Emby.Server.Implementations.TV namespace Emby.Server.Implementations.TV
{ {
@ -73,7 +77,8 @@ namespace Emby.Server.Implementations.TV
{ {
parents = _libraryManager.GetUserRootFolder().GetChildren(user, true) parents = _libraryManager.GetUserRootFolder().GetChildren(user, true)
.Where(i => i is Folder) .Where(i => i is Folder)
.Where(i => !user.Configuration.LatestItemsExcludes.Contains(i.Id.ToString("N", CultureInfo.InvariantCulture))) .Where(i => !user.GetPreference(PreferenceKind.LatestItemExcludes)
.Contains(i.Id.ToString("N", CultureInfo.InvariantCulture)))
.ToArray(); .ToArray();
} }
@ -191,7 +196,7 @@ namespace Emby.Server.Implementations.TV
{ {
AncestorWithPresentationUniqueKey = null, AncestorWithPresentationUniqueKey = null,
SeriesPresentationUniqueKey = seriesKey, SeriesPresentationUniqueKey = seriesKey,
IncludeItemTypes = new[] { typeof(Episode).Name }, IncludeItemTypes = new[] { nameof(Episode) },
OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Descending) }, OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Descending) },
IsPlayed = true, IsPlayed = true,
Limit = 1, Limit = 1,
@ -204,7 +209,6 @@ namespace Emby.Server.Implementations.TV
}, },
EnableImages = false EnableImages = false
} }
}).FirstOrDefault(); }).FirstOrDefault();
Func<Episode> getEpisode = () => Func<Episode> getEpisode = () =>
@ -219,9 +223,8 @@ namespace Emby.Server.Implementations.TV
IsPlayed = false, IsPlayed = false,
IsVirtualItem = false, IsVirtualItem = false,
ParentIndexNumberNotEquals = 0, ParentIndexNumberNotEquals = 0,
MinSortName = lastWatchedEpisode == null ? null : lastWatchedEpisode.SortName, MinSortName = lastWatchedEpisode?.SortName,
DtoOptions = dtoOptions DtoOptions = dtoOptions
}).Cast<Episode>().FirstOrDefault(); }).Cast<Episode>().FirstOrDefault();
}; };

View File

@ -3,6 +3,7 @@ using System.Security.Claims;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Constants; using Jellyfin.Api.Constants;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -49,10 +50,10 @@ namespace Jellyfin.Api.Auth
var claims = new[] var claims = new[]
{ {
new Claim(ClaimTypes.Name, user.Name), new Claim(ClaimTypes.Name, user.Username),
new Claim( new Claim(
ClaimTypes.Role, ClaimTypes.Role,
value: user.Policy.IsAdministrator ? UserRoles.Administrator : UserRoles.User) value: user.HasPermission(PermissionKind.IsAdministrator) ? UserRoles.Administrator : UserRoles.User)
}; };
var identity = new ClaimsIdentity(claims, Scheme.Name); var identity = new ClaimsIdentity(claims, Scheme.Name);
var principal = new ClaimsPrincipal(identity); var principal = new ClaimsPrincipal(identity);

View File

@ -95,10 +95,12 @@ namespace Jellyfin.Api.Controllers
[HttpGet("User")] [HttpGet("User")]
public StartupUserDto GetFirstUser() public StartupUserDto GetFirstUser()
{ {
// TODO: Remove this method when startup wizard no longer requires an existing user.
_userManager.Initialize();
var user = _userManager.Users.First(); var user = _userManager.Users.First();
return new StartupUserDto return new StartupUserDto
{ {
Name = user.Name, Name = user.Username,
Password = user.Password Password = user.Password
}; };
} }
@ -113,9 +115,9 @@ namespace Jellyfin.Api.Controllers
{ {
var user = _userManager.Users.First(); var user = _userManager.Users.First();
user.Name = startupUserDto.Name; user.Username = startupUserDto.Name;
_userManager.UpdateUser(user); await _userManager.UpdateUserAsync(user).ConfigureAwait(false);
if (!string.IsNullOrEmpty(startupUserDto.Password)) if (!string.IsNullOrEmpty(startupUserDto.Password))
{ {

View File

@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using Jellyfin.Data.Enums;
namespace Jellyfin.Data
{
public static class DayOfWeekHelper
{
public static List<DayOfWeek> GetDaysOfWeek(DynamicDayOfWeek day)
{
var days = new List<DayOfWeek>(7);
if (day == DynamicDayOfWeek.Sunday
|| day == DynamicDayOfWeek.Weekend
|| day == DynamicDayOfWeek.Everyday)
{
days.Add(DayOfWeek.Sunday);
}
if (day == DynamicDayOfWeek.Monday
|| day == DynamicDayOfWeek.Weekday
|| day == DynamicDayOfWeek.Everyday)
{
days.Add(DayOfWeek.Monday);
}
if (day == DynamicDayOfWeek.Tuesday
|| day == DynamicDayOfWeek.Weekday
|| day == DynamicDayOfWeek.Everyday)
{
days.Add(DayOfWeek.Tuesday);
}
if (day == DynamicDayOfWeek.Wednesday
|| day == DynamicDayOfWeek.Weekday
|| day == DynamicDayOfWeek.Everyday)
{
days.Add(DayOfWeek.Wednesday);
}
if (day == DynamicDayOfWeek.Thursday
|| day == DynamicDayOfWeek.Weekday
|| day == DynamicDayOfWeek.Everyday)
{
days.Add(DayOfWeek.Thursday);
}
if (day == DynamicDayOfWeek.Friday
|| day == DynamicDayOfWeek.Weekday
|| day == DynamicDayOfWeek.Everyday)
{
days.Add(DayOfWeek.Friday);
}
if (day == DynamicDayOfWeek.Saturday
|| day == DynamicDayOfWeek.Weekend
|| day == DynamicDayOfWeek.Everyday)
{
days.Add(DayOfWeek.Saturday);
}
return days;
}
}
}

View File

@ -0,0 +1,91 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
using System.Xml.Serialization;
using Jellyfin.Data.Enums;
namespace Jellyfin.Data.Entities
{
/// <summary>
/// An entity representing a user's access schedule.
/// </summary>
public class AccessSchedule
{
/// <summary>
/// Initializes a new instance of the <see cref="AccessSchedule"/> class.
/// </summary>
/// <param name="dayOfWeek">The day of the week.</param>
/// <param name="startHour">The start hour.</param>
/// <param name="endHour">The end hour.</param>
/// <param name="userId">The associated user's id.</param>
public AccessSchedule(DynamicDayOfWeek dayOfWeek, double startHour, double endHour, Guid userId)
{
UserId = userId;
DayOfWeek = dayOfWeek;
StartHour = startHour;
EndHour = endHour;
}
/// <summary>
/// Initializes a new instance of the <see cref="AccessSchedule"/> class.
/// Default constructor. Protected due to required properties, but present because EF needs it.
/// </summary>
protected AccessSchedule()
{
}
/// <summary>
/// Gets or sets the id of this instance.
/// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[XmlIgnore]
[Key]
[Required]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; protected set; }
/// <summary>
/// Gets or sets the id of the associated user.
/// </summary>
[XmlIgnore]
[Required]
public Guid UserId { get; protected set; }
/// <summary>
/// Gets or sets the day of week.
/// </summary>
/// <value>The day of week.</value>
[Required]
public DynamicDayOfWeek DayOfWeek { get; set; }
/// <summary>
/// Gets or sets the start hour.
/// </summary>
/// <value>The start hour.</value>
[Required]
public double StartHour { get; set; }
/// <summary>
/// Gets or sets the end hour.
/// </summary>
/// <value>The end hour.</value>
[Required]
public double EndHour { get; set; }
/// <summary>
/// Static create function (for use in LINQ queries, etc.)
/// </summary>
/// <param name="dayOfWeek">The day of the week.</param>
/// <param name="startHour">The start hour.</param>
/// <param name="endHour">The end hour.</param>
/// <param name="userId">The associated user's id.</param>
/// <returns>The newly created instance.</returns>
public static AccessSchedule Create(DynamicDayOfWeek dayOfWeek, double startHour, double endHour, Guid userId)
{
return new AccessSchedule(dayOfWeek, startHour, endHour, userId);
}
}
}

View File

@ -189,7 +189,6 @@ namespace Jellyfin.Data.Entities
/************************************************************************* /*************************************************************************
* Navigation properties * Navigation properties
*************************************************************************/ *************************************************************************/
} }
} }

View File

@ -63,7 +63,6 @@ namespace Jellyfin.Data.Entities
[ForeignKey("Release_Releases_Id")] [ForeignKey("Release_Releases_Id")]
public virtual ICollection<Release> Releases { get; protected set; } public virtual ICollection<Release> Releases { get; protected set; }
} }
} }

View File

@ -101,7 +101,6 @@ namespace Jellyfin.Data.Entities
[ForeignKey("Company_Publishers_Id")] [ForeignKey("Company_Publishers_Id")]
public virtual ICollection<Company> Publishers { get; protected set; } public virtual ICollection<Company> Publishers { get; protected set; }
} }
} }

View File

@ -257,7 +257,6 @@ namespace Jellyfin.Data.Entities
/************************************************************************* /*************************************************************************
* Navigation properties * Navigation properties
*************************************************************************/ *************************************************************************/
} }
} }

View File

@ -114,7 +114,6 @@ namespace Jellyfin.Data.Entities
*************************************************************************/ *************************************************************************/
[ForeignKey("CollectionItem_CollectionItem_Id")] [ForeignKey("CollectionItem_CollectionItem_Id")]
public virtual ICollection<CollectionItem> CollectionItem { get; protected set; } public virtual ICollection<CollectionItem> CollectionItem { get; protected set; }
} }
} }

View File

@ -137,7 +137,6 @@ namespace Jellyfin.Data.Entities
/// </remarks> /// </remarks>
[ForeignKey("CollectionItem_Previous_Id")] [ForeignKey("CollectionItem_Previous_Id")]
public virtual CollectionItem Previous { get; set; } public virtual CollectionItem Previous { get; set; }
} }
} }

View File

@ -131,7 +131,6 @@ namespace Jellyfin.Data.Entities
public virtual ICollection<CompanyMetadata> CompanyMetadata { get; protected set; } public virtual ICollection<CompanyMetadata> CompanyMetadata { get; protected set; }
[ForeignKey("Company_Parent_Id")] [ForeignKey("Company_Parent_Id")]
public virtual Company Parent { get; set; } public virtual Company Parent { get; set; }
} }
} }

View File

@ -210,7 +210,6 @@ namespace Jellyfin.Data.Entities
/************************************************************************* /*************************************************************************
* Navigation properties * Navigation properties
*************************************************************************/ *************************************************************************/
} }
} }

View File

@ -62,7 +62,6 @@ namespace Jellyfin.Data.Entities
[ForeignKey("Release_Releases_Id")] [ForeignKey("Release_Releases_Id")]
public virtual ICollection<Release> Releases { get; protected set; } public virtual ICollection<Release> Releases { get; protected set; }
} }
} }

View File

@ -61,7 +61,6 @@ namespace Jellyfin.Data.Entities
/************************************************************************* /*************************************************************************
* Navigation properties * Navigation properties
*************************************************************************/ *************************************************************************/
} }
} }

View File

@ -104,7 +104,6 @@ namespace Jellyfin.Data.Entities
public virtual ICollection<Release> Releases { get; protected set; } public virtual ICollection<Release> Releases { get; protected set; }
[ForeignKey("EpisodeMetadata_EpisodeMetadata_Id")] [ForeignKey("EpisodeMetadata_EpisodeMetadata_Id")]
public virtual ICollection<EpisodeMetadata> EpisodeMetadata { get; protected set; } public virtual ICollection<EpisodeMetadata> EpisodeMetadata { get; protected set; }
} }
} }

View File

@ -173,7 +173,6 @@ namespace Jellyfin.Data.Entities
/************************************************************************* /*************************************************************************
* Navigation properties * Navigation properties
*************************************************************************/ *************************************************************************/
} }
} }

View File

@ -146,7 +146,6 @@ namespace Jellyfin.Data.Entities
/************************************************************************* /*************************************************************************
* Navigation properties * Navigation properties
*************************************************************************/ *************************************************************************/
} }
} }

View File

@ -2,19 +2,32 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using Jellyfin.Data.Enums;
namespace Jellyfin.Data.Entities namespace Jellyfin.Data.Entities
{ {
public partial class Group
{
partial void Init();
/// <summary> /// <summary>
/// Default constructor. Protected due to required properties, but present because EF needs it. /// An entity representing a group.
/// </summary> /// </summary>
protected Group() public partial class Group : IHasPermissions, ISavingChanges
{ {
GroupPermissions = new HashSet<Permission>(); /// <summary>
/// Initializes a new instance of the <see cref="Group"/> class.
/// Public constructor with required data.
/// </summary>
/// <param name="name">The name of the group.</param>
public Group(string name)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException(nameof(name));
}
Name = name;
Id = Guid.NewGuid();
Permissions = new HashSet<Permission>();
ProviderMappings = new HashSet<ProviderMapping>(); ProviderMappings = new HashSet<ProviderMapping>();
Preferences = new HashSet<Preference>(); Preferences = new HashSet<Preference>();
@ -22,66 +35,45 @@ namespace Jellyfin.Data.Entities
} }
/// <summary> /// <summary>
/// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. /// Initializes a new instance of the <see cref="Group"/> class.
/// Default constructor. Protected due to required properties, but present because EF needs it.
/// </summary> /// </summary>
public static Group CreateGroupUnsafe() protected Group()
{ {
return new Group();
}
/// <summary>
/// Public constructor with required data
/// </summary>
/// <param name="name"></param>
/// <param name="_user0"></param>
public Group(string name, User _user0)
{
if (string.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name));
this.Name = name;
if (_user0 == null) throw new ArgumentNullException(nameof(_user0));
_user0.Groups.Add(this);
this.GroupPermissions = new HashSet<Permission>();
this.ProviderMappings = new HashSet<ProviderMapping>();
this.Preferences = new HashSet<Preference>();
Init(); Init();
} }
/// <summary>
/// Static create function (for use in LINQ queries, etc.)
/// </summary>
/// <param name="name"></param>
/// <param name="_user0"></param>
public static Group Create(string name, User _user0)
{
return new Group(name, _user0);
}
/************************************************************************* /*************************************************************************
* Properties * Properties
*************************************************************************/ *************************************************************************/
/// <summary> /// <summary>
/// Identity, Indexed, Required /// Gets or sets the id of this group.
/// </summary> /// </summary>
/// <remarks>
/// Identity, Indexed, Required.
/// </remarks>
[Key] [Key]
[Required] [Required]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] public Guid Id { get; protected set; }
public int Id { get; protected set; }
/// <summary> /// <summary>
/// Required, Max length = 255 /// Gets or sets the group's name.
/// </summary> /// </summary>
/// <remarks>
/// Required, Max length = 255.
/// </remarks>
[Required] [Required]
[MaxLength(255)] [MaxLength(255)]
[StringLength(255)] [StringLength(255)]
public string Name { get; set; } public string Name { get; set; }
/// <summary> /// <summary>
/// Required, ConcurrenyToken /// Gets or sets the row version.
/// </summary> /// </summary>
/// <remarks>
/// Required, Concurrency Token.
/// </remarks>
[ConcurrencyCheck] [ConcurrencyCheck]
[Required] [Required]
public uint RowVersion { get; set; } public uint RowVersion { get; set; }
@ -96,7 +88,7 @@ namespace Jellyfin.Data.Entities
*************************************************************************/ *************************************************************************/
[ForeignKey("Permission_GroupPermissions_Id")] [ForeignKey("Permission_GroupPermissions_Id")]
public virtual ICollection<Permission> GroupPermissions { get; protected set; } public virtual ICollection<Permission> Permissions { get; protected set; }
[ForeignKey("ProviderMapping_ProviderMappings_Id")] [ForeignKey("ProviderMapping_ProviderMappings_Id")]
public virtual ICollection<ProviderMapping> ProviderMappings { get; protected set; } public virtual ICollection<ProviderMapping> ProviderMappings { get; protected set; }
@ -104,6 +96,27 @@ namespace Jellyfin.Data.Entities
[ForeignKey("Preference_Preferences_Id")] [ForeignKey("Preference_Preferences_Id")]
public virtual ICollection<Preference> Preferences { get; protected set; } public virtual ICollection<Preference> Preferences { get; protected set; }
} /// <summary>
/// Static create function (for use in LINQ queries, etc.)
/// </summary>
/// <param name="name">The name of this group</param>
public static Group Create(string name)
{
return new Group(name);
} }
/// <inheritdoc/>
public bool HasPermission(PermissionKind kind)
{
return Permissions.First(p => p.Kind == kind).Value;
}
/// <inheritdoc/>
public void SetPermission(PermissionKind kind, bool value)
{
Permissions.First(p => p.Kind == kind).Value = value;
}
partial void Init();
}
}

View File

@ -0,0 +1,30 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Jellyfin.Data.Entities
{
public class ImageInfo
{
public ImageInfo(string path)
{
Path = path;
LastModified = DateTime.UtcNow;
}
[Key]
[Required]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; protected set; }
public Guid? UserId { get; protected set; }
[Required]
[MaxLength(512)]
[StringLength(512)]
public string Path { get; set; }
[Required]
public DateTime LastModified { get; set; }
}
}

View File

@ -141,7 +141,6 @@ namespace Jellyfin.Data.Entities
/************************************************************************* /*************************************************************************
* Navigation properties * Navigation properties
*************************************************************************/ *************************************************************************/
} }
} }

View File

@ -164,7 +164,6 @@ namespace Jellyfin.Data.Entities
/// </summary> /// </summary>
[ForeignKey("LibraryRoot_Id")] [ForeignKey("LibraryRoot_Id")]
public virtual LibraryRoot LibraryRoot { get; set; } public virtual LibraryRoot LibraryRoot { get; set; }
} }
} }

View File

@ -186,7 +186,6 @@ namespace Jellyfin.Data.Entities
/// </summary> /// </summary>
[ForeignKey("Library_Id")] [ForeignKey("Library_Id")]
public virtual Library Library { get; set; } public virtual Library Library { get; set; }
} }
} }

View File

@ -194,7 +194,6 @@ namespace Jellyfin.Data.Entities
[ForeignKey("MediaFileStream_MediaFileStreams_Id")] [ForeignKey("MediaFileStream_MediaFileStreams_Id")]
public virtual ICollection<MediaFileStream> MediaFileStreams { get; protected set; } public virtual ICollection<MediaFileStream> MediaFileStreams { get; protected set; }
} }
} }

View File

@ -143,7 +143,6 @@ namespace Jellyfin.Data.Entities
/************************************************************************* /*************************************************************************
* Navigation properties * Navigation properties
*************************************************************************/ *************************************************************************/
} }
} }

Some files were not shown because too many files have changed in this diff Show More