Bläddra i källkod

Use new entities for API key endpoints

Patrick Barron 4 år sedan
förälder
incheckning
499785bebb

+ 18 - 34
Jellyfin.Api/Controllers/ApiKeyController.cs

@@ -1,10 +1,8 @@
 using System;
 using System.ComponentModel.DataAnnotations;
-using System.Globalization;
+using System.Threading.Tasks;
 using Jellyfin.Api.Constants;
-using MediaBrowser.Controller;
 using MediaBrowser.Controller.Security;
-using MediaBrowser.Controller.Session;
 using MediaBrowser.Model.Querying;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Http;
@@ -18,24 +16,15 @@ namespace Jellyfin.Api.Controllers
     [Route("Auth")]
     public class ApiKeyController : BaseJellyfinApiController
     {
-        private readonly ISessionManager _sessionManager;
-        private readonly IServerApplicationHost _appHost;
-        private readonly IAuthenticationRepository _authRepo;
+        private readonly IAuthenticationManager _authenticationManager;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="ApiKeyController"/> class.
         /// </summary>
-        /// <param name="sessionManager">Instance of <see cref="ISessionManager"/> interface.</param>
-        /// <param name="appHost">Instance of <see cref="IServerApplicationHost"/> interface.</param>
-        /// <param name="authRepo">Instance of <see cref="IAuthenticationRepository"/> interface.</param>
-        public ApiKeyController(
-            ISessionManager sessionManager,
-            IServerApplicationHost appHost,
-            IAuthenticationRepository authRepo)
+        /// <param name="authenticationManager">Instance of <see cref="IAuthenticationManager"/> interface.</param>
+        public ApiKeyController(IAuthenticationManager authenticationManager)
         {
-            _sessionManager = sessionManager;
-            _appHost = appHost;
-            _authRepo = authRepo;
+            _authenticationManager = authenticationManager;
         }
 
         /// <summary>
@@ -46,14 +35,15 @@ namespace Jellyfin.Api.Controllers
         [HttpGet("Keys")]
         [Authorize(Policy = Policies.RequiresElevation)]
         [ProducesResponseType(StatusCodes.Status200OK)]
-        public ActionResult<QueryResult<AuthenticationInfo>> GetKeys()
+        public async Task<ActionResult<QueryResult<AuthenticationInfo>>> GetKeys()
         {
-            var result = _authRepo.Get(new AuthenticationInfoQuery
-            {
-                HasUser = false
-            });
+            var keys = await _authenticationManager.GetApiKeys();
 
-            return result;
+            return new QueryResult<AuthenticationInfo>
+            {
+                Items = keys,
+                TotalRecordCount = keys.Count
+            };
         }
 
         /// <summary>
@@ -65,17 +55,10 @@ namespace Jellyfin.Api.Controllers
         [HttpPost("Keys")]
         [Authorize(Policy = Policies.RequiresElevation)]
         [ProducesResponseType(StatusCodes.Status204NoContent)]
-        public ActionResult CreateKey([FromQuery, Required] string app)
+        public async Task<ActionResult> CreateKey([FromQuery, Required] string app)
         {
-            _authRepo.Create(new AuthenticationInfo
-            {
-                AppName = app,
-                AccessToken = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture),
-                DateCreated = DateTime.UtcNow,
-                DeviceId = _appHost.SystemId,
-                DeviceName = _appHost.FriendlyName,
-                AppVersion = _appHost.ApplicationVersionString
-            });
+            await _authenticationManager.CreateApiKey(app).ConfigureAwait(false);
+
             return NoContent();
         }
 
@@ -88,9 +71,10 @@ namespace Jellyfin.Api.Controllers
         [HttpDelete("Keys/{key}")]
         [Authorize(Policy = Policies.RequiresElevation)]
         [ProducesResponseType(StatusCodes.Status204NoContent)]
-        public ActionResult RevokeKey([FromRoute, Required] string key)
+        public async Task<ActionResult> RevokeKey([FromRoute, Required] Guid key)
         {
-            _sessionManager.RevokeToken(key);
+            await _authenticationManager.DeleteApiKey(key).ConfigureAwait(false);
+
             return NoContent();
         }
     }

+ 74 - 0
Jellyfin.Server.Implementations/Security/AuthenticationManager.cs

@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Threading.Tasks;
+using Jellyfin.Data.Entities.Security;
+using MediaBrowser.Controller.Security;
+using Microsoft.EntityFrameworkCore;
+
+namespace Jellyfin.Server.Implementations.Security
+{
+    /// <inheritdoc />
+    public class AuthenticationManager : IAuthenticationManager
+    {
+        private readonly JellyfinDbProvider _dbProvider;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AuthenticationManager"/> class.
+        /// </summary>
+        /// <param name="dbProvider">The database provider.</param>
+        public AuthenticationManager(JellyfinDbProvider dbProvider)
+        {
+            _dbProvider = dbProvider;
+        }
+
+        /// <inheritdoc />
+        public async Task CreateApiKey(string name)
+        {
+            await using var dbContext = _dbProvider.CreateContext();
+
+            dbContext.ApiKeys.Add(new ApiKey(name));
+
+            await dbContext.SaveChangesAsync().ConfigureAwait(false);
+        }
+
+        /// <inheritdoc />
+        public async Task<IReadOnlyList<AuthenticationInfo>> GetApiKeys()
+        {
+            await using var dbContext = _dbProvider.CreateContext();
+
+            return await dbContext.ApiKeys
+                .AsAsyncEnumerable()
+                .Select(key => new AuthenticationInfo
+                {
+                    AppName = key.Name,
+                    AccessToken = key.AccessToken.ToString("N", CultureInfo.InvariantCulture),
+                    DateCreated = key.DateCreated,
+                    DeviceId = string.Empty,
+                    DeviceName = string.Empty,
+                    AppVersion = string.Empty
+                }).ToListAsync().ConfigureAwait(false);
+        }
+
+        /// <inheritdoc />
+        public async Task DeleteApiKey(Guid id)
+        {
+            await using var dbContext = _dbProvider.CreateContext();
+
+            var key = await dbContext.ApiKeys
+                .AsQueryable()
+                .Where(apiKey => apiKey.AccessToken == id)
+                .FirstOrDefaultAsync();
+
+            if (key == null)
+            {
+                return;
+            }
+
+            dbContext.Remove(key);
+
+            await dbContext.SaveChangesAsync().ConfigureAwait(false);
+        }
+    }
+}

+ 34 - 0
MediaBrowser.Controller/Security/IAuthenticationManager.cs

@@ -0,0 +1,34 @@
+#nullable enable
+
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Security
+{
+    /// <summary>
+    /// Handles the retrieval and storage of API keys.
+    /// </summary>
+    public interface IAuthenticationManager
+    {
+        /// <summary>
+        /// Creates an API key.
+        /// </summary>
+        /// <param name="name">The name of the key.</param>
+        /// <returns>A task representing the creation of the key.</returns>
+        Task CreateApiKey(string name);
+
+        /// <summary>
+        /// Gets the API keys.
+        /// </summary>
+        /// <returns>A task representing the retrieval of the API keys.</returns>
+        Task<IReadOnlyList<AuthenticationInfo>> GetApiKeys();
+
+        /// <summary>
+        /// Deletes an API key with the provided access token.
+        /// </summary>
+        /// <param name="accessToken">The access token.</param>
+        /// <returns>A task representing the deletion of the API key.</returns>
+        Task DeleteApiKey(Guid accessToken);
+    }
+}