mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-06-03 06:18:28 +01:00
remove JellyfinDbProvider and add second level caching
This commit is contained in:
@@ -10,13 +10,13 @@ namespace Jellyfin.Server.Implementations.Security
|
||||
/// <inheritdoc />
|
||||
public class AuthenticationManager : IAuthenticationManager
|
||||
{
|
||||
private readonly JellyfinDbProvider _dbProvider;
|
||||
private readonly IDbContextFactory<JellyfinDb> _dbProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AuthenticationManager"/> class.
|
||||
/// </summary>
|
||||
/// <param name="dbProvider">The database provider.</param>
|
||||
public AuthenticationManager(JellyfinDbProvider dbProvider)
|
||||
public AuthenticationManager(IDbContextFactory<JellyfinDb> dbProvider)
|
||||
{
|
||||
_dbProvider = dbProvider;
|
||||
}
|
||||
@@ -24,50 +24,56 @@ namespace Jellyfin.Server.Implementations.Security
|
||||
/// <inheritdoc />
|
||||
public async Task CreateApiKey(string name)
|
||||
{
|
||||
await using var dbContext = _dbProvider.CreateContext();
|
||||
var dbContext = await _dbProvider.CreateDbContextAsync().ConfigureAwait(false);
|
||||
await using (dbContext.ConfigureAwait(false))
|
||||
{
|
||||
dbContext.ApiKeys.Add(new ApiKey(name));
|
||||
|
||||
dbContext.ApiKeys.Add(new ApiKey(name));
|
||||
|
||||
await dbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
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,
|
||||
DateCreated = key.DateCreated,
|
||||
DeviceId = string.Empty,
|
||||
DeviceName = string.Empty,
|
||||
AppVersion = string.Empty
|
||||
}).ToListAsync().ConfigureAwait(false);
|
||||
var dbContext = await _dbProvider.CreateDbContextAsync().ConfigureAwait(false);
|
||||
await using (dbContext.ConfigureAwait(false))
|
||||
{
|
||||
return await dbContext.ApiKeys
|
||||
.AsAsyncEnumerable()
|
||||
.Select(key => new AuthenticationInfo
|
||||
{
|
||||
AppName = key.Name,
|
||||
AccessToken = key.AccessToken,
|
||||
DateCreated = key.DateCreated,
|
||||
DeviceId = string.Empty,
|
||||
DeviceName = string.Empty,
|
||||
AppVersion = string.Empty
|
||||
}).ToListAsync().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task DeleteApiKey(string accessToken)
|
||||
{
|
||||
await using var dbContext = _dbProvider.CreateContext();
|
||||
|
||||
var key = await dbContext.ApiKeys
|
||||
.AsQueryable()
|
||||
.Where(apiKey => apiKey.AccessToken == accessToken)
|
||||
.FirstOrDefaultAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (key == null)
|
||||
var dbContext = await _dbProvider.CreateDbContextAsync().ConfigureAwait(false);
|
||||
await using (dbContext.ConfigureAwait(false))
|
||||
{
|
||||
return;
|
||||
var key = await dbContext.ApiKeys
|
||||
.AsQueryable()
|
||||
.Where(apiKey => apiKey.AccessToken == accessToken)
|
||||
.FirstOrDefaultAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (key == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
dbContext.Remove(key);
|
||||
|
||||
await dbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
dbContext.Remove(key);
|
||||
|
||||
await dbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using EFCoreSecondLevelCacheInterceptor;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Net;
|
||||
@@ -15,12 +16,12 @@ namespace Jellyfin.Server.Implementations.Security
|
||||
{
|
||||
public class AuthorizationContext : IAuthorizationContext
|
||||
{
|
||||
private readonly JellyfinDbProvider _jellyfinDbProvider;
|
||||
private readonly IDbContextFactory<JellyfinDb> _jellyfinDbProvider;
|
||||
private readonly IUserManager _userManager;
|
||||
private readonly IServerApplicationHost _serverApplicationHost;
|
||||
|
||||
public AuthorizationContext(
|
||||
JellyfinDbProvider jellyfinDb,
|
||||
IDbContextFactory<JellyfinDb> jellyfinDb,
|
||||
IUserManager userManager,
|
||||
IServerApplicationHost serverApplicationHost)
|
||||
{
|
||||
@@ -121,96 +122,99 @@ namespace Jellyfin.Server.Implementations.Security
|
||||
#pragma warning restore CA1508
|
||||
|
||||
authInfo.HasToken = true;
|
||||
await using var dbContext = _jellyfinDbProvider.CreateContext();
|
||||
var device = await dbContext.Devices.FirstOrDefaultAsync(d => d.AccessToken == token).ConfigureAwait(false);
|
||||
|
||||
if (device != null)
|
||||
var dbContext = await _jellyfinDbProvider.CreateDbContextAsync().ConfigureAwait(false);
|
||||
await using (dbContext.ConfigureAwait(false))
|
||||
{
|
||||
authInfo.IsAuthenticated = true;
|
||||
var updateToken = false;
|
||||
var device = await dbContext.Devices.FirstOrDefaultAsync(d => d.AccessToken == token).ConfigureAwait(false);
|
||||
|
||||
// TODO: Remove these checks for IsNullOrWhiteSpace
|
||||
if (string.IsNullOrWhiteSpace(authInfo.Client))
|
||||
{
|
||||
authInfo.Client = device.AppName;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(authInfo.DeviceId))
|
||||
{
|
||||
authInfo.DeviceId = device.DeviceId;
|
||||
}
|
||||
|
||||
// Temporary. TODO - allow clients to specify that the token has been shared with a casting device
|
||||
var allowTokenInfoUpdate = !authInfo.Client.Contains("chromecast", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(authInfo.Device))
|
||||
{
|
||||
authInfo.Device = device.DeviceName;
|
||||
}
|
||||
else if (!string.Equals(authInfo.Device, device.DeviceName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (allowTokenInfoUpdate)
|
||||
{
|
||||
updateToken = true;
|
||||
device.DeviceName = authInfo.Device;
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(authInfo.Version))
|
||||
{
|
||||
authInfo.Version = device.AppVersion;
|
||||
}
|
||||
else if (!string.Equals(authInfo.Version, device.AppVersion, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (allowTokenInfoUpdate)
|
||||
{
|
||||
updateToken = true;
|
||||
device.AppVersion = authInfo.Version;
|
||||
}
|
||||
}
|
||||
|
||||
if ((DateTime.UtcNow - device.DateLastActivity).TotalMinutes > 3)
|
||||
{
|
||||
device.DateLastActivity = DateTime.UtcNow;
|
||||
updateToken = true;
|
||||
}
|
||||
|
||||
authInfo.User = _userManager.GetUserById(device.UserId);
|
||||
|
||||
if (updateToken)
|
||||
{
|
||||
dbContext.Devices.Update(device);
|
||||
await dbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var key = await dbContext.ApiKeys.FirstOrDefaultAsync(apiKey => apiKey.AccessToken == token).ConfigureAwait(false);
|
||||
if (key != null)
|
||||
if (device != null)
|
||||
{
|
||||
authInfo.IsAuthenticated = true;
|
||||
authInfo.Client = key.Name;
|
||||
authInfo.Token = key.AccessToken;
|
||||
var updateToken = false;
|
||||
|
||||
// TODO: Remove these checks for IsNullOrWhiteSpace
|
||||
if (string.IsNullOrWhiteSpace(authInfo.Client))
|
||||
{
|
||||
authInfo.Client = device.AppName;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(authInfo.DeviceId))
|
||||
{
|
||||
authInfo.DeviceId = _serverApplicationHost.SystemId;
|
||||
authInfo.DeviceId = device.DeviceId;
|
||||
}
|
||||
|
||||
// Temporary. TODO - allow clients to specify that the token has been shared with a casting device
|
||||
var allowTokenInfoUpdate = !authInfo.Client.Contains("chromecast", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(authInfo.Device))
|
||||
{
|
||||
authInfo.Device = _serverApplicationHost.Name;
|
||||
authInfo.Device = device.DeviceName;
|
||||
}
|
||||
else if (!string.Equals(authInfo.Device, device.DeviceName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (allowTokenInfoUpdate)
|
||||
{
|
||||
updateToken = true;
|
||||
device.DeviceName = authInfo.Device;
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(authInfo.Version))
|
||||
{
|
||||
authInfo.Version = _serverApplicationHost.ApplicationVersionString;
|
||||
authInfo.Version = device.AppVersion;
|
||||
}
|
||||
else if (!string.Equals(authInfo.Version, device.AppVersion, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (allowTokenInfoUpdate)
|
||||
{
|
||||
updateToken = true;
|
||||
device.AppVersion = authInfo.Version;
|
||||
}
|
||||
}
|
||||
|
||||
authInfo.IsApiKey = true;
|
||||
}
|
||||
}
|
||||
if ((DateTime.UtcNow - device.DateLastActivity).TotalMinutes > 3)
|
||||
{
|
||||
device.DateLastActivity = DateTime.UtcNow;
|
||||
updateToken = true;
|
||||
}
|
||||
|
||||
return authInfo;
|
||||
authInfo.User = _userManager.GetUserById(device.UserId);
|
||||
|
||||
if (updateToken)
|
||||
{
|
||||
dbContext.Devices.Update(device);
|
||||
await dbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var key = await dbContext.ApiKeys.FirstOrDefaultAsync(apiKey => apiKey.AccessToken == token).ConfigureAwait(false);
|
||||
if (key != null)
|
||||
{
|
||||
authInfo.IsAuthenticated = true;
|
||||
authInfo.Client = key.Name;
|
||||
authInfo.Token = key.AccessToken;
|
||||
if (string.IsNullOrWhiteSpace(authInfo.DeviceId))
|
||||
{
|
||||
authInfo.DeviceId = _serverApplicationHost.SystemId;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(authInfo.Device))
|
||||
{
|
||||
authInfo.Device = _serverApplicationHost.Name;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(authInfo.Version))
|
||||
{
|
||||
authInfo.Version = _serverApplicationHost.ApplicationVersionString;
|
||||
}
|
||||
|
||||
authInfo.IsApiKey = true;
|
||||
}
|
||||
}
|
||||
|
||||
return authInfo;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user