Sfoglia il codice sorgente

Enable nullable for AuthorizationInfo (#13485)

Bond-009 4 mesi fa
parent
commit
00b66a06ea

+ 7 - 6
Jellyfin.Api/Auth/CustomAuthenticationHandler.cs

@@ -50,20 +50,21 @@ namespace Jellyfin.Api.Auth
                 }
 
                 var role = UserRoles.User;
-                if (authorizationInfo.IsApiKey || authorizationInfo.User.HasPermission(PermissionKind.IsAdministrator))
+                if (authorizationInfo.IsApiKey
+                    || (authorizationInfo.User?.HasPermission(PermissionKind.IsAdministrator) ?? false))
                 {
                     role = UserRoles.Administrator;
                 }
 
                 var claims = new[]
                 {
-                    new Claim(ClaimTypes.Name, authorizationInfo.User.Username),
+                    new Claim(ClaimTypes.Name, authorizationInfo.User?.Username ?? string.Empty),
                     new Claim(ClaimTypes.Role, role),
                     new Claim(InternalClaimTypes.UserId, authorizationInfo.UserId.ToString("N", CultureInfo.InvariantCulture)),
-                    new Claim(InternalClaimTypes.DeviceId, authorizationInfo.DeviceId),
-                    new Claim(InternalClaimTypes.Device, authorizationInfo.Device),
-                    new Claim(InternalClaimTypes.Client, authorizationInfo.Client),
-                    new Claim(InternalClaimTypes.Version, authorizationInfo.Version),
+                    new Claim(InternalClaimTypes.DeviceId, authorizationInfo.DeviceId ?? string.Empty),
+                    new Claim(InternalClaimTypes.Device, authorizationInfo.Device ?? string.Empty),
+                    new Claim(InternalClaimTypes.Client, authorizationInfo.Client ?? string.Empty),
+                    new Claim(InternalClaimTypes.Version, authorizationInfo.Version ?? string.Empty),
                     new Claim(InternalClaimTypes.Token, authorizationInfo.Token),
                     new Claim(InternalClaimTypes.IsApiKey, authorizationInfo.IsApiKey.ToString(CultureInfo.InvariantCulture))
                 };

+ 2 - 1
Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs

@@ -70,7 +70,8 @@ public class ActivityLogWebSocketListener : BasePeriodicWebSocketListener<Activi
     /// <param name="message">The message.</param>
     protected override void Start(WebSocketMessageInfo message)
     {
-        if (!message.Connection.AuthorizationInfo.User.HasPermission(PermissionKind.IsAdministrator))
+        if (message.Connection.AuthorizationInfo.User is null
+            || !message.Connection.AuthorizationInfo.User.HasPermission(PermissionKind.IsAdministrator))
         {
             throw new AuthenticationException("Only admin users can retrieve the activity log.");
         }

+ 2 - 1
Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs

@@ -79,7 +79,8 @@ public class SessionInfoWebSocketListener : BasePeriodicWebSocketListener<IEnume
     /// <param name="message">The message.</param>
     protected override void Start(WebSocketMessageInfo message)
     {
-        if (!message.Connection.AuthorizationInfo.User.HasPermission(PermissionKind.IsAdministrator))
+        if (message.Connection.AuthorizationInfo.User is null
+            || !message.Connection.AuthorizationInfo.User.HasPermission(PermissionKind.IsAdministrator))
         {
             throw new AuthenticationException("Only admin users can subscribe to session information.");
         }

+ 2 - 4
Jellyfin.Server.Implementations/Security/AuthorizationContext.cs

@@ -116,17 +116,15 @@ namespace Jellyfin.Server.Implementations.Security
                 DeviceId = deviceId,
                 Version = version,
                 Token = token,
-                IsAuthenticated = false,
-                HasToken = false
+                IsAuthenticated = false
             };
 
-            if (string.IsNullOrWhiteSpace(token))
+            if (!authInfo.HasToken)
             {
                 // Request doesn't contain a token.
                 return authInfo;
             }
 
-            authInfo.HasToken = true;
             var dbContext = await _jellyfinDbProvider.CreateDbContextAsync().ConfigureAwait(false);
             await using (dbContext.ConfigureAwait(false))
             {

+ 10 - 10
MediaBrowser.Controller/Net/AuthorizationInfo.cs

@@ -1,6 +1,5 @@
-#nullable disable
-
 using System;
+using System.Diagnostics.CodeAnalysis;
 using Jellyfin.Data.Entities;
 
 namespace MediaBrowser.Controller.Net
@@ -20,31 +19,31 @@ namespace MediaBrowser.Controller.Net
         /// Gets or sets the device identifier.
         /// </summary>
         /// <value>The device identifier.</value>
-        public string DeviceId { get; set; }
+        public string? DeviceId { get; set; }
 
         /// <summary>
         /// Gets or sets the device.
         /// </summary>
         /// <value>The device.</value>
-        public string Device { get; set; }
+        public string? Device { get; set; }
 
         /// <summary>
         /// Gets or sets the client.
         /// </summary>
         /// <value>The client.</value>
-        public string Client { get; set; }
+        public string? Client { get; set; }
 
         /// <summary>
         /// Gets or sets the version.
         /// </summary>
         /// <value>The version.</value>
-        public string Version { get; set; }
+        public string? Version { get; set; }
 
         /// <summary>
         /// Gets or sets the token.
         /// </summary>
         /// <value>The token.</value>
-        public string Token { get; set; }
+        public string? Token { get; set; }
 
         /// <summary>
         /// Gets or sets a value indicating whether the authorization is from an api key.
@@ -54,7 +53,7 @@ namespace MediaBrowser.Controller.Net
         /// <summary>
         /// Gets or sets the user making the request.
         /// </summary>
-        public User User { get; set; }
+        public User? User { get; set; }
 
         /// <summary>
         /// Gets or sets a value indicating whether the token is authenticated.
@@ -62,8 +61,9 @@ namespace MediaBrowser.Controller.Net
         public bool IsAuthenticated { get; set; }
 
         /// <summary>
-        /// Gets or sets a value indicating whether the request has a token.
+        /// Gets a value indicating whether the request has a token.
         /// </summary>
-        public bool HasToken { get; set; }
+        [MemberNotNullWhen(true, nameof(Token))]
+        public bool HasToken => !string.IsNullOrWhiteSpace(Token);
     }
 }

+ 2 - 1
tests/Jellyfin.Api.Tests/Auth/CustomAuthenticationHandlerTests.cs

@@ -100,6 +100,7 @@ namespace Jellyfin.Api.Tests.Auth
             var authorizationInfo = SetupUser();
             var authenticateResult = await _sut.AuthenticateAsync();
 
+            Assert.NotNull(authorizationInfo.User);
             Assert.True(authenticateResult.Principal?.HasClaim(ClaimTypes.Name, authorizationInfo.User.Username));
         }
 
@@ -111,6 +112,7 @@ namespace Jellyfin.Api.Tests.Auth
             var authorizationInfo = SetupUser(isAdmin);
             var authenticateResult = await _sut.AuthenticateAsync();
 
+            Assert.NotNull(authorizationInfo.User);
             var expectedRole = authorizationInfo.User.HasPermission(PermissionKind.IsAdministrator) ? UserRoles.Administrator : UserRoles.User;
             Assert.True(authenticateResult.Principal?.HasClaim(ClaimTypes.Role, expectedRole));
         }
@@ -132,7 +134,6 @@ namespace Jellyfin.Api.Tests.Auth
             authorizationInfo.User.AddDefaultPreferences();
             authorizationInfo.User.SetPermission(PermissionKind.IsAdministrator, isAdmin);
             authorizationInfo.IsApiKey = false;
-            authorizationInfo.HasToken = true;
             authorizationInfo.Token = "fake-token";
 
             _jellyfinAuthServiceMock.Setup(