This commit is contained in:
KGT1 2025-08-02 06:59:41 -04:00 committed by GitHub
commit 0e50f0e389
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 42 additions and 12 deletions

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Data; using Jellyfin.Data;
using Jellyfin.Database.Implementations.Enums; using Jellyfin.Database.Implementations.Enums;
@ -56,6 +57,25 @@ public class SessionInfoWebSocketListener : BasePeriodicWebSocketListener<IEnume
return Task.FromResult(_sessionManager.Sessions); return Task.FromResult(_sessionManager.Sessions);
} }
/// <summary>
/// Gets the data to send for a specific connection.
/// </summary>
/// <param name="connection">The connection.</param>
/// <returns>Task{IEnumerable{SessionInfo}}.</returns>
protected override Task<IEnumerable<SessionInfo>> GetDataToSendForConnection(IWebSocketConnection connection)
{
// For non-admin users, filter the sessions to only include their own sessions
if (connection.AuthorizationInfo?.User != null &&
!connection.AuthorizationInfo.IsApiKey &&
!connection.AuthorizationInfo.User.HasPermission(PermissionKind.IsAdministrator))
{
var userId = connection.AuthorizationInfo.User.Id;
return Task.FromResult(_sessionManager.Sessions.Where(s => s.UserId.Equals(userId) || s.ContainsUser(userId)));
}
return Task.FromResult(_sessionManager.Sessions);
}
/// <inheritdoc /> /// <inheritdoc />
protected override async ValueTask DisposeAsyncCore() protected override async ValueTask DisposeAsyncCore()
{ {
@ -80,11 +100,10 @@ public class SessionInfoWebSocketListener : BasePeriodicWebSocketListener<IEnume
/// <param name="message">The message.</param> /// <param name="message">The message.</param>
protected override void Start(WebSocketMessageInfo message) protected override void Start(WebSocketMessageInfo message)
{ {
if (!message.Connection.AuthorizationInfo.IsApiKey // Allow all authenticated users to subscribe to session information
&& (message.Connection.AuthorizationInfo.User is null if (message.Connection.AuthorizationInfo.User is null && !message.Connection.AuthorizationInfo.IsApiKey)
|| !message.Connection.AuthorizationInfo.User.HasPermission(PermissionKind.IsAdministrator)))
{ {
throw new AuthenticationException("Only admin users can subscribe to session information."); throw new AuthenticationException("User must be authenticated to subscribe to session Information.");
} }
base.Start(message); base.Start(message);

View File

@ -80,6 +80,16 @@ namespace MediaBrowser.Controller.Net
/// <returns>Task{`1}.</returns> /// <returns>Task{`1}.</returns>
protected abstract Task<TReturnDataType> GetDataToSend(); protected abstract Task<TReturnDataType> GetDataToSend();
/// <summary>
/// Gets the data to send for a specific connection.
/// </summary>
/// <param name="connection">The connection.</param>
/// <returns>Task{`1}.</returns>
protected virtual Task<TReturnDataType> GetDataToSendForConnection(IWebSocketConnection connection)
{
return GetDataToSend();
}
/// <summary> /// <summary>
/// Processes the message. /// Processes the message.
/// </summary> /// </summary>
@ -174,17 +184,11 @@ namespace MediaBrowser.Controller.Net
continue; continue;
} }
var data = await GetDataToSend().ConfigureAwait(false);
if (data is null)
{
continue;
}
IEnumerable<Task> GetTasks() IEnumerable<Task> GetTasks()
{ {
foreach (var tuple in tuples) foreach (var tuple in tuples)
{ {
yield return SendDataInternal(data, tuple); yield return SendDataForConnectionAsync(tuple);
} }
} }
@ -198,12 +202,19 @@ namespace MediaBrowser.Controller.Net
} }
} }
private async Task SendDataInternal(TReturnDataType data, (IWebSocketConnection Connection, CancellationTokenSource CancellationTokenSource, TStateType State) tuple) private async Task SendDataForConnectionAsync((IWebSocketConnection Connection, CancellationTokenSource CancellationTokenSource, TStateType State) tuple)
{ {
try try
{ {
var (connection, cts, state) = tuple; var (connection, cts, state) = tuple;
var cancellationToken = cts.Token; var cancellationToken = cts.Token;
var data = await GetDataToSendForConnection(connection).ConfigureAwait(false);
if (data is null)
{
return;
}
await connection.SendAsync( await connection.SendAsync(
new OutboundWebSocketMessage<TReturnDataType> { MessageType = Type, Data = data }, new OutboundWebSocketMessage<TReturnDataType> { MessageType = Type, Data = data },
cancellationToken).ConfigureAwait(false); cancellationToken).ConfigureAwait(false);