From a0c6f7276211ac0429877fafa400368aba1430a9 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Thu, 20 May 2021 23:56:59 -0400 Subject: Migrate authentication db to EF Core --- .../Security/AuthorizationContext.cs | 283 +++++++++++++++++++++ 1 file changed, 283 insertions(+) create mode 100644 Jellyfin.Server.Implementations/Security/AuthorizationContext.cs (limited to 'Jellyfin.Server.Implementations/Security/AuthorizationContext.cs') diff --git a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs new file mode 100644 index 0000000000..775edafc2d --- /dev/null +++ b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs @@ -0,0 +1,283 @@ +#pragma warning disable CS1591 + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Net; +using Microsoft.AspNetCore.Http; +using Microsoft.Net.Http.Headers; + +namespace Jellyfin.Server.Implementations.Security +{ + public class AuthorizationContext : IAuthorizationContext + { + private readonly JellyfinDb _jellyfinDb; + private readonly IUserManager _userManager; + + public AuthorizationContext(JellyfinDb jellyfinDb, IUserManager userManager) + { + _jellyfinDb = jellyfinDb; + _userManager = userManager; + } + + public Task GetAuthorizationInfo(HttpContext requestContext) + { + if (requestContext.Request.HttpContext.Items.TryGetValue("AuthorizationInfo", out var cached) && cached != null) + { + return Task.FromResult((AuthorizationInfo)cached); + } + + return GetAuthorization(requestContext); + } + + public async Task GetAuthorizationInfo(HttpRequest requestContext) + { + var auth = GetAuthorizationDictionary(requestContext); + var authInfo = await GetAuthorizationInfoFromDictionary(auth, requestContext.Headers, requestContext.Query).ConfigureAwait(false); + return authInfo; + } + + /// + /// Gets the authorization. + /// + /// The HTTP req. + /// Dictionary{System.StringSystem.String}. + private async Task GetAuthorization(HttpContext httpReq) + { + var auth = GetAuthorizationDictionary(httpReq); + var authInfo = await GetAuthorizationInfoFromDictionary(auth, httpReq.Request.Headers, httpReq.Request.Query).ConfigureAwait(false); + + httpReq.Request.HttpContext.Items["AuthorizationInfo"] = authInfo; + return authInfo; + } + + private async Task GetAuthorizationInfoFromDictionary( + IReadOnlyDictionary? auth, + IHeaderDictionary headers, + IQueryCollection queryString) + { + string? deviceId = null; + string? deviceName = null; + string? client = null; + string? version = null; + string? token = null; + + if (auth != null) + { + auth.TryGetValue("DeviceId", out deviceId); + auth.TryGetValue("Device", out deviceName); + auth.TryGetValue("Client", out client); + auth.TryGetValue("Version", out version); + auth.TryGetValue("Token", out token); + } + +#pragma warning disable CA1508 + // headers can return StringValues.Empty + if (string.IsNullOrEmpty(token)) + { + token = headers["X-Emby-Token"]; + } + + if (string.IsNullOrEmpty(token)) + { + token = headers["X-MediaBrowser-Token"]; + } + + if (string.IsNullOrEmpty(token)) + { + token = queryString["ApiKey"]; + } + + // TODO deprecate this query parameter. + if (string.IsNullOrEmpty(token)) + { + token = queryString["api_key"]; + } + + var authInfo = new AuthorizationInfo + { + Client = client, + Device = deviceName, + DeviceId = deviceId, + Version = version, + Token = token, + IsAuthenticated = false, + HasToken = false + }; + + if (string.IsNullOrWhiteSpace(token)) + { + // Request doesn't contain a token. + return authInfo; + } +#pragma warning restore CA1508 + + authInfo.HasToken = true; + var device = await _jellyfinDb.Devices.FirstOrDefaultAsync(d => d.AccessToken == token).ConfigureAwait(false); + + if (device != null) + { + authInfo.IsAuthenticated = true; + } + + if (device != null) + { + 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 = 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; + } + + if (!device.UserId.Equals(Guid.Empty)) + { + authInfo.User = _userManager.GetUserById(device.UserId); + authInfo.IsApiKey = false; + } + else + { + authInfo.IsApiKey = true; + } + + if (updateToken) + { + _jellyfinDb.Devices.Update(device); + await _jellyfinDb.SaveChangesAsync().ConfigureAwait(false); + } + } + + return authInfo; + } + + /// + /// Gets the auth. + /// + /// The HTTP req. + /// Dictionary{System.StringSystem.String}. + private Dictionary? GetAuthorizationDictionary(HttpContext httpReq) + { + var auth = httpReq.Request.Headers["X-Emby-Authorization"]; + + if (string.IsNullOrEmpty(auth)) + { + auth = httpReq.Request.Headers[HeaderNames.Authorization]; + } + + return GetAuthorization(auth); + } + + /// + /// Gets the auth. + /// + /// The HTTP req. + /// Dictionary{System.StringSystem.String}. + private Dictionary? GetAuthorizationDictionary(HttpRequest httpReq) + { + var auth = httpReq.Headers["X-Emby-Authorization"]; + + if (string.IsNullOrEmpty(auth)) + { + auth = httpReq.Headers[HeaderNames.Authorization]; + } + + return GetAuthorization(auth); + } + + /// + /// Gets the authorization. + /// + /// The authorization header. + /// Dictionary{System.StringSystem.String}. + private Dictionary? GetAuthorization(string? authorizationHeader) + { + if (authorizationHeader == null) + { + return null; + } + + var parts = authorizationHeader.Split(' ', 2); + + // There should be at least to parts + if (parts.Length != 2) + { + return null; + } + + var acceptedNames = new[] { "MediaBrowser", "Emby" }; + + // It has to be a digest request + if (!acceptedNames.Contains(parts[0], StringComparer.OrdinalIgnoreCase)) + { + return null; + } + + // Remove uptil the first space + authorizationHeader = parts[1]; + parts = authorizationHeader.Split(','); + + var result = new Dictionary(StringComparer.OrdinalIgnoreCase); + + foreach (var item in parts) + { + var param = item.Trim().Split('=', 2); + + if (param.Length == 2) + { + var value = NormalizeValue(param[1].Trim('"')); + result[param[0]] = value; + } + } + + return result; + } + + private static string NormalizeValue(string value) + { + return string.IsNullOrEmpty(value) ? value : WebUtility.HtmlEncode(value); + } + } +} -- cgit v1.2.3 From 37a8a82ac54a795402006b116a9ef5ece4a3eb6c Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Fri, 21 May 2021 00:19:54 -0400 Subject: Make methods static in AuthenticationContext --- Jellyfin.Server.Implementations/Security/AuthorizationContext.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Jellyfin.Server.Implementations/Security/AuthorizationContext.cs') diff --git a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs index 688ff71682..b10b7a9985 100644 --- a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs +++ b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs @@ -199,7 +199,7 @@ namespace Jellyfin.Server.Implementations.Security /// /// The HTTP req. /// Dictionary{System.StringSystem.String}. - private Dictionary? GetAuthorizationDictionary(HttpContext httpReq) + private static Dictionary? GetAuthorizationDictionary(HttpContext httpReq) { var auth = httpReq.Request.Headers["X-Emby-Authorization"]; @@ -216,7 +216,7 @@ namespace Jellyfin.Server.Implementations.Security /// /// The HTTP req. /// Dictionary{System.StringSystem.String}. - private Dictionary? GetAuthorizationDictionary(HttpRequest httpReq) + private static Dictionary? GetAuthorizationDictionary(HttpRequest httpReq) { var auth = httpReq.Headers["X-Emby-Authorization"]; @@ -233,7 +233,7 @@ namespace Jellyfin.Server.Implementations.Security /// /// The authorization header. /// Dictionary{System.StringSystem.String}. - private Dictionary? GetAuthorization(ReadOnlySpan authorizationHeader) + private static Dictionary? GetAuthorization(ReadOnlySpan authorizationHeader) { var firstSpace = authorizationHeader.IndexOf(' '); -- cgit v1.2.3 From 3d9c16ba6b8be965da8ed57510f8f90831ed1e22 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Fri, 18 Jun 2021 17:06:38 -0400 Subject: Fix concurrency issues --- .../Security/AuthorizationContext.cs | 13 +++++++------ Jellyfin.Server/CoreAppHost.cs | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'Jellyfin.Server.Implementations/Security/AuthorizationContext.cs') diff --git a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs index b10b7a9985..92be5477cb 100644 --- a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs +++ b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs @@ -15,12 +15,12 @@ namespace Jellyfin.Server.Implementations.Security { public class AuthorizationContext : IAuthorizationContext { - private readonly JellyfinDb _jellyfinDb; + private readonly JellyfinDbProvider _jellyfinDbProvider; private readonly IUserManager _userManager; - public AuthorizationContext(JellyfinDb jellyfinDb, IUserManager userManager) + public AuthorizationContext(JellyfinDbProvider jellyfinDb, IUserManager userManager) { - _jellyfinDb = jellyfinDb; + _jellyfinDbProvider = jellyfinDb; _userManager = userManager; } @@ -117,7 +117,8 @@ namespace Jellyfin.Server.Implementations.Security #pragma warning restore CA1508 authInfo.HasToken = true; - var device = await _jellyfinDb.Devices.FirstOrDefaultAsync(d => d.AccessToken == token).ConfigureAwait(false); + await using var jellyfinDb = _jellyfinDbProvider.CreateContext(); + var device = await jellyfinDb.Devices.FirstOrDefaultAsync(d => d.AccessToken == token).ConfigureAwait(false); if (device != null) { @@ -186,8 +187,8 @@ namespace Jellyfin.Server.Implementations.Security if (updateToken) { - _jellyfinDb.Devices.Update(device); - await _jellyfinDb.SaveChangesAsync().ConfigureAwait(false); + jellyfinDb.Devices.Update(device); + await jellyfinDb.SaveChangesAsync().ConfigureAwait(false); } } diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index 362be85316..e480b9a69a 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -95,7 +95,7 @@ namespace Jellyfin.Server ServiceCollection.AddSingleton(); ServiceCollection.AddSingleton(); - ServiceCollection.AddScoped(); + ServiceCollection.AddSingleton(); base.RegisterServices(); } -- cgit v1.2.3 From 4206c0e0910e257f2fa05db7e63b554919d799b3 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Fri, 18 Jun 2021 17:09:39 -0400 Subject: Combine if statements --- Jellyfin.Server.Implementations/Security/AuthorizationContext.cs | 4 ---- 1 file changed, 4 deletions(-) (limited to 'Jellyfin.Server.Implementations/Security/AuthorizationContext.cs') diff --git a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs index 92be5477cb..4b073ed33e 100644 --- a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs +++ b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs @@ -123,10 +123,6 @@ namespace Jellyfin.Server.Implementations.Security if (device != null) { authInfo.IsAuthenticated = true; - } - - if (device != null) - { var updateToken = false; // TODO: Remove these checks for IsNullOrWhiteSpace -- cgit v1.2.3 From 0292936c659b25464c1bc1e1b80711f873a1a7cd Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Fri, 18 Jun 2021 17:09:59 -0400 Subject: Use consistent name for db context --- Jellyfin.Server.Implementations/Security/AuthorizationContext.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Jellyfin.Server.Implementations/Security/AuthorizationContext.cs') diff --git a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs index 4b073ed33e..e589fae301 100644 --- a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs +++ b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs @@ -117,8 +117,8 @@ namespace Jellyfin.Server.Implementations.Security #pragma warning restore CA1508 authInfo.HasToken = true; - await using var jellyfinDb = _jellyfinDbProvider.CreateContext(); - var device = await jellyfinDb.Devices.FirstOrDefaultAsync(d => d.AccessToken == token).ConfigureAwait(false); + await using var dbContext = _jellyfinDbProvider.CreateContext(); + var device = await dbContext.Devices.FirstOrDefaultAsync(d => d.AccessToken == token).ConfigureAwait(false); if (device != null) { @@ -183,8 +183,8 @@ namespace Jellyfin.Server.Implementations.Security if (updateToken) { - jellyfinDb.Devices.Update(device); - await jellyfinDb.SaveChangesAsync().ConfigureAwait(false); + dbContext.Devices.Update(device); + await dbContext.SaveChangesAsync().ConfigureAwait(false); } } -- cgit v1.2.3 From 336ba2879f325a4efd52bc7737ce94f40369bfeb Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Fri, 18 Jun 2021 18:26:58 -0400 Subject: Re-add support for API keys --- Jellyfin.Api/Controllers/ApiKeyController.cs | 2 +- Jellyfin.Data/Entities/Security/ApiKey.cs | 5 +++-- .../Security/AuthenticationManager.cs | 8 +++----- .../Security/AuthorizationContext.cs | 13 +++++++++++++ .../Migrations/Routines/MigrateAuthenticationDb.cs | 2 +- MediaBrowser.Controller/Security/IAuthenticationManager.cs | 2 +- 6 files changed, 22 insertions(+), 10 deletions(-) (limited to 'Jellyfin.Server.Implementations/Security/AuthorizationContext.cs') diff --git a/Jellyfin.Api/Controllers/ApiKeyController.cs b/Jellyfin.Api/Controllers/ApiKeyController.cs index 96efde5fbd..720b22b1d6 100644 --- a/Jellyfin.Api/Controllers/ApiKeyController.cs +++ b/Jellyfin.Api/Controllers/ApiKeyController.cs @@ -71,7 +71,7 @@ namespace Jellyfin.Api.Controllers [HttpDelete("Keys/{key}")] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] - public async Task RevokeKey([FromRoute, Required] Guid key) + public async Task RevokeKey([FromRoute, Required] string key) { await _authenticationManager.DeleteApiKey(key).ConfigureAwait(false); diff --git a/Jellyfin.Data/Entities/Security/ApiKey.cs b/Jellyfin.Data/Entities/Security/ApiKey.cs index 5c9ac5d5b8..31d865d018 100644 --- a/Jellyfin.Data/Entities/Security/ApiKey.cs +++ b/Jellyfin.Data/Entities/Security/ApiKey.cs @@ -1,6 +1,7 @@ using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using System.Globalization; namespace Jellyfin.Data.Entities.Security { @@ -17,7 +18,7 @@ namespace Jellyfin.Data.Entities.Security { Name = name; - AccessToken = Guid.NewGuid(); + AccessToken = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture); DateCreated = DateTime.UtcNow; } @@ -50,6 +51,6 @@ namespace Jellyfin.Data.Entities.Security /// /// Gets or sets the access token. /// - public Guid AccessToken { get; set; } + public string AccessToken { get; set; } } } diff --git a/Jellyfin.Server.Implementations/Security/AuthenticationManager.cs b/Jellyfin.Server.Implementations/Security/AuthenticationManager.cs index ab76e2302f..b79e46469c 100644 --- a/Jellyfin.Server.Implementations/Security/AuthenticationManager.cs +++ b/Jellyfin.Server.Implementations/Security/AuthenticationManager.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Globalization; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Jellyfin.Data.Entities.Security; @@ -43,7 +41,7 @@ namespace Jellyfin.Server.Implementations.Security .Select(key => new AuthenticationInfo { AppName = key.Name, - AccessToken = key.AccessToken.ToString("N", CultureInfo.InvariantCulture), + AccessToken = key.AccessToken, DateCreated = key.DateCreated, DeviceId = string.Empty, DeviceName = string.Empty, @@ -52,7 +50,7 @@ namespace Jellyfin.Server.Implementations.Security } /// - public async Task DeleteApiKey(Guid accessToken) + public async Task DeleteApiKey(string accessToken) { await using var dbContext = _dbProvider.CreateContext(); diff --git a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs index e589fae301..9a073c4770 100644 --- a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs +++ b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs @@ -187,6 +187,19 @@ namespace Jellyfin.Server.Implementations.Security 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; + authInfo.DeviceId = string.Empty; + authInfo.Device = string.Empty; + authInfo.Version = string.Empty; + } + } return authInfo; } diff --git a/Jellyfin.Server/Migrations/Routines/MigrateAuthenticationDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateAuthenticationDb.cs index 10afc52a19..9bcf245d38 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateAuthenticationDb.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateAuthenticationDb.cs @@ -61,7 +61,7 @@ namespace Jellyfin.Server.Migrations.Routines { dbContext.ApiKeys.Add(new ApiKey(row[3].ToString()) { - AccessToken = row[1].ToGuid(), + AccessToken = row[1].ToString(), DateCreated = row[9].ToDateTime(), DateLastActivity = row[10].ToDateTime() }); diff --git a/MediaBrowser.Controller/Security/IAuthenticationManager.cs b/MediaBrowser.Controller/Security/IAuthenticationManager.cs index 46d0c66224..29621b73e7 100644 --- a/MediaBrowser.Controller/Security/IAuthenticationManager.cs +++ b/MediaBrowser.Controller/Security/IAuthenticationManager.cs @@ -29,6 +29,6 @@ namespace MediaBrowser.Controller.Security /// /// The access token. /// A task representing the deletion of the API key. - Task DeleteApiKey(Guid accessToken); + Task DeleteApiKey(string accessToken); } } -- cgit v1.2.3 From fdba71e133f980cfbea3e198cf5236528e753fa2 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sun, 27 Jun 2021 16:44:34 -0400 Subject: Fix Api Key authentication --- .../Security/AuthorizationContext.cs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'Jellyfin.Server.Implementations/Security/AuthorizationContext.cs') diff --git a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs index 08970f84de..8a5d513efa 100644 --- a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs +++ b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs @@ -171,15 +171,7 @@ namespace Jellyfin.Server.Implementations.Security updateToken = true; } - if (!device.UserId.Equals(Guid.Empty)) - { - authInfo.User = _userManager.GetUserById(device.UserId); - authInfo.IsApiKey = false; - } - else - { - authInfo.IsApiKey = true; - } + authInfo.User = _userManager.GetUserById(device.UserId); if (updateToken) { @@ -198,6 +190,7 @@ namespace Jellyfin.Server.Implementations.Security authInfo.DeviceId = string.Empty; authInfo.Device = string.Empty; authInfo.Version = string.Empty; + authInfo.IsApiKey = true; } } -- cgit v1.2.3 From 60185f99c4329da7c93cc3769c4c017aab61b6bf Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 3 Sep 2021 21:43:06 +0200 Subject: fix the build --- Jellyfin.Server.Implementations/Security/AuthorizationContext.cs | 1 - .../DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'Jellyfin.Server.Implementations/Security/AuthorizationContext.cs') diff --git a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs index d993ca2345..e559d698a3 100644 --- a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs +++ b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Linq; using System.Net; using System.Threading.Tasks; -using Jellyfin.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using Microsoft.AspNetCore.Http; diff --git a/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs b/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs index 5387922ab9..312dffde23 100644 --- a/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs +++ b/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs @@ -1,10 +1,10 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; using AutoFixture; using AutoFixture.AutoMoq; -using Emby.Server.Implementations.HttpServer.Security; using Jellyfin.Api.Auth.DefaultAuthorizationPolicy; using Jellyfin.Api.Constants; +using Jellyfin.Server.Implementations.Security; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Library; using Microsoft.AspNetCore.Authorization; -- cgit v1.2.3 From 1172ece856d91d060ba5122269fc9ea55f336495 Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 3 Sep 2021 23:56:19 +0200 Subject: remove leading and trailing whitespace from the key --- .../Security/AuthorizationContext.cs | 2 +- .../DefaultAuthorizationHandlerTests.cs | 59 +++++++++++++++++++--- 2 files changed, 54 insertions(+), 7 deletions(-) (limited to 'Jellyfin.Server.Implementations/Security/AuthorizationContext.cs') diff --git a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs index e559d698a3..244abf469e 100644 --- a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs +++ b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs @@ -291,7 +291,7 @@ namespace Jellyfin.Server.Implementations.Security } else if (!escaped && token == '=') { - key = authorizationHeader[start.. i].ToString(); + key = authorizationHeader[start.. i].Trim().ToString(); start = i + 1; } } diff --git a/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs b/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs index 312dffde23..ee4af34ad5 100644 --- a/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs +++ b/tests/Jellyfin.Api.Tests/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandlerTests.cs @@ -52,14 +52,61 @@ namespace Jellyfin.Api.Tests.Auth.DefaultAuthorizationPolicy } [Theory] - [InlineData("x=\"123,123\",y=\"123\"", "x", "123,123")] - [InlineData("x=\"ab\"", "x", "ab")] - [InlineData("param=Hörbücher", "param", "Hörbücher")] - [InlineData("param=%22%Hörbücher", "param", "\"%Hörbücher")] - public void TestAuthHeaders(string input, string key, string value) + [MemberData(nameof(GetParts_ValidAuthHeader_Success_Data))] + public void GetParts_ValidAuthHeader_Success(string input, Dictionary parts) { var dict = AuthorizationContext.GetParts(input); - Assert.True(string.Equals(dict[key], value, System.StringComparison.Ordinal)); + foreach (var (key, value) in parts) + { + Assert.Equal(dict[key], value); + } + } + + private static TheoryData> GetParts_ValidAuthHeader_Success_Data() + { + var data = new TheoryData>(); + + data.Add( + "x=\"123,123\",y=\"123\"", + new Dictionary + { + { "x", "123,123" }, + { "y", "123" } + }); + + data.Add( + "x=\"123,123\", y=\"123\",z=\"'hi'\"", + new Dictionary + { + { "x", "123,123" }, + { "y", "123" }, + { "z", "'hi'" } + }); + + data.Add( + "x=\"ab\"", + new Dictionary + { + { "x", "ab" } + }); + + data.Add( + "param=Hörbücher", + new Dictionary + { + { "param", "Hörbücher" } + } + ); + + data.Add( + "param=%22%Hörbücher", + new Dictionary + { + { "param", "\"%Hörbücher" } + } + ); + + return data; } } } -- cgit v1.2.3 From 7c282ec3694d8e6a127588c41cd0c68f8ee4e93b Mon Sep 17 00:00:00 2001 From: KonH Date: Sun, 3 Oct 2021 10:43:05 +0700 Subject: Fix warning: The nullable warning suppression expression is redundant (#2149) --- .../Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs | 4 ++-- Jellyfin.Api/Controllers/DashboardController.cs | 2 +- Jellyfin.Api/Controllers/DynamicHlsController.cs | 2 +- Jellyfin.Api/Controllers/HlsSegmentController.cs | 4 ++-- Jellyfin.Api/Controllers/InstantMixController.cs | 14 +++++++------- Jellyfin.Api/Controllers/ItemsController.cs | 2 +- Jellyfin.Api/Controllers/MediaInfoController.cs | 2 +- Jellyfin.Api/Controllers/TvShowsController.cs | 8 ++++---- Jellyfin.Api/Controllers/UniversalAudioController.cs | 2 +- Jellyfin.Api/Controllers/VideosController.cs | 2 +- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 8 ++++---- Jellyfin.Api/Models/StreamingDtos/StreamState.cs | 2 +- .../Security/AuthorizationContext.cs | 2 +- 13 files changed, 27 insertions(+), 27 deletions(-) (limited to 'Jellyfin.Server.Implementations/Security/AuthorizationContext.cs') diff --git a/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs b/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs index b898ac76c8..e6c04eb082 100644 --- a/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs +++ b/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs @@ -51,7 +51,7 @@ namespace Jellyfin.Api.Auth.SyncPlayAccessPolicy { if (user.SyncPlayAccess == SyncPlayUserAccessType.CreateAndJoinGroups || user.SyncPlayAccess == SyncPlayUserAccessType.JoinGroups - || _syncPlayManager.IsUserActive(userId!.Value)) + || _syncPlayManager.IsUserActive(userId.Value)) { context.Succeed(requirement); } @@ -85,7 +85,7 @@ namespace Jellyfin.Api.Auth.SyncPlayAccessPolicy } else if (requirement.RequiredAccess == SyncPlayAccessRequirementType.IsInGroup) { - if (_syncPlayManager.IsUserActive(userId!.Value)) + if (_syncPlayManager.IsUserActive(userId.Value)) { context.Succeed(requirement); } diff --git a/Jellyfin.Api/Controllers/DashboardController.cs b/Jellyfin.Api/Controllers/DashboardController.cs index 445733c24d..87cb418d97 100644 --- a/Jellyfin.Api/Controllers/DashboardController.cs +++ b/Jellyfin.Api/Controllers/DashboardController.cs @@ -53,7 +53,7 @@ namespace Jellyfin.Api.Controllers if (enableInMainMenu.HasValue) { - configPages = configPages.Where(p => p!.EnableInMainMenu == enableInMainMenu.Value).ToList(); + configPages = configPages.Where(p => p.EnableInMainMenu == enableInMainMenu.Value).ToList(); } return configPages; diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index a540033579..42e82dd5b1 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -1709,7 +1709,7 @@ namespace Jellyfin.Api.Controllers return Task.CompletedTask; }); - return FileStreamResponseHelpers.GetStaticFileResult(segmentPath, MimeTypes.GetMimeType(segmentPath)!, false, HttpContext); + return FileStreamResponseHelpers.GetStaticFileResult(segmentPath, MimeTypes.GetMimeType(segmentPath), false, HttpContext); } private long GetEndPositionTicks(StreamState state, int requestedIndex) diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index 473bdc523c..71caa0fe0d 100644 --- a/Jellyfin.Api/Controllers/HlsSegmentController.cs +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -69,7 +69,7 @@ namespace Jellyfin.Api.Controllers return BadRequest("Invalid segment."); } - return FileStreamResponseHelpers.GetStaticFileResult(file, MimeTypes.GetMimeType(file)!, false, HttpContext); + return FileStreamResponseHelpers.GetStaticFileResult(file, MimeTypes.GetMimeType(file), false, HttpContext); } /// @@ -186,7 +186,7 @@ namespace Jellyfin.Api.Controllers return Task.CompletedTask; }); - return FileStreamResponseHelpers.GetStaticFileResult(path, MimeTypes.GetMimeType(path)!, false, HttpContext); + return FileStreamResponseHelpers.GetStaticFileResult(path, MimeTypes.GetMimeType(path), false, HttpContext); } } } diff --git a/Jellyfin.Api/Controllers/InstantMixController.cs b/Jellyfin.Api/Controllers/InstantMixController.cs index 4774ed4efa..a6c2e07c93 100644 --- a/Jellyfin.Api/Controllers/InstantMixController.cs +++ b/Jellyfin.Api/Controllers/InstantMixController.cs @@ -80,7 +80,7 @@ namespace Jellyfin.Api.Controllers : null; var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) - .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!); + .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); } @@ -116,7 +116,7 @@ namespace Jellyfin.Api.Controllers : null; var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) - .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!); + .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(album, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); } @@ -152,7 +152,7 @@ namespace Jellyfin.Api.Controllers : null; var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) - .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!); + .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(playlist, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); } @@ -187,7 +187,7 @@ namespace Jellyfin.Api.Controllers : null; var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) - .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!); + .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromGenres(new[] { name }, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); } @@ -223,7 +223,7 @@ namespace Jellyfin.Api.Controllers : null; var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) - .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!); + .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); } @@ -259,7 +259,7 @@ namespace Jellyfin.Api.Controllers : null; var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) - .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!); + .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); } @@ -332,7 +332,7 @@ namespace Jellyfin.Api.Controllers : null; var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) - .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!); + .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); } diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs index 52eefc5c23..f0d44e5cc8 100644 --- a/Jellyfin.Api/Controllers/ItemsController.cs +++ b/Jellyfin.Api/Controllers/ItemsController.cs @@ -287,7 +287,7 @@ namespace Jellyfin.Api.Controllers if ((recursive.HasValue && recursive.Value) || ids.Length != 0 || item is not UserRootFolder) { - var query = new InternalItemsQuery(user!) + var query = new InternalItemsQuery(user) { IsPlayed = isPlayed, MediaTypes = mediaTypes, diff --git a/Jellyfin.Api/Controllers/MediaInfoController.cs b/Jellyfin.Api/Controllers/MediaInfoController.cs index 7c78928f72..96ef2d678b 100644 --- a/Jellyfin.Api/Controllers/MediaInfoController.cs +++ b/Jellyfin.Api/Controllers/MediaInfoController.cs @@ -184,7 +184,7 @@ namespace Jellyfin.Api.Controllers audioStreamIndex, subtitleStreamIndex, maxAudioChannels, - info!.PlaySessionId!, + info.PlaySessionId!, userId ?? Guid.Empty, enableDirectPlay.Value, enableDirectStream.Value, diff --git a/Jellyfin.Api/Controllers/TvShowsController.cs b/Jellyfin.Api/Controllers/TvShowsController.cs index 6eada67cf0..5dd7733316 100644 --- a/Jellyfin.Api/Controllers/TvShowsController.cs +++ b/Jellyfin.Api/Controllers/TvShowsController.cs @@ -88,7 +88,7 @@ namespace Jellyfin.Api.Controllers { var options = new DtoOptions { Fields = fields } .AddClientFields(Request) - .AddAdditionalDtoOptions(enableImges, enableUserData, imageTypeLimit, enableImageTypes!); + .AddAdditionalDtoOptions(enableImges, enableUserData, imageTypeLimit, enableImageTypes); var result = _tvSeriesManager.GetNextUp( new NextUpQuery @@ -153,7 +153,7 @@ namespace Jellyfin.Api.Controllers var options = new DtoOptions { Fields = fields } .AddClientFields(Request) - .AddAdditionalDtoOptions(enableImges, enableUserData, imageTypeLimit, enableImageTypes!); + .AddAdditionalDtoOptions(enableImges, enableUserData, imageTypeLimit, enableImageTypes); var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user) { @@ -223,7 +223,7 @@ namespace Jellyfin.Api.Controllers var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) - .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!); + .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); if (seasonId.HasValue) // Season id was supplied. Get episodes by season id. { @@ -350,7 +350,7 @@ namespace Jellyfin.Api.Controllers var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) - .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!); + .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var returnItems = _dtoService.GetBaseItemDtos(seasons, dtoOptions, user); diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs index 20a02bf4a9..bc9527a0bc 100644 --- a/Jellyfin.Api/Controllers/UniversalAudioController.cs +++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs @@ -155,7 +155,7 @@ namespace Jellyfin.Api.Controllers null, null, maxAudioChannels, - info!.PlaySessionId!, + info.PlaySessionId!, userId ?? Guid.Empty, true, true, diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs index 150f22d1b8..e1cbc6f331 100644 --- a/Jellyfin.Api/Controllers/VideosController.cs +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -461,7 +461,7 @@ namespace Jellyfin.Api.Controllers var liveStream = new ProgressiveFileStream(liveStreamInfo.GetStream()); // TODO (moved from MediaBrowser.Api): Don't hardcode contentType - return File(liveStream, MimeTypes.GetMimeType("file.ts")!); + return File(liveStream, MimeTypes.GetMimeType("file.ts")); } // Static remote stream diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 14f287aef6..488856c4ea 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -86,8 +86,8 @@ namespace Jellyfin.Api.Helpers DeleteEncodedMediaCache(); - sessionManager!.PlaybackProgress += OnPlaybackProgress; - sessionManager!.PlaybackStart += OnPlaybackProgress; + sessionManager.PlaybackProgress += OnPlaybackProgress; + sessionManager.PlaybackStart += OnPlaybackProgress; } /// @@ -878,8 +878,8 @@ namespace Jellyfin.Api.Helpers if (disposing) { _loggerFactory.Dispose(); - _sessionManager!.PlaybackProgress -= OnPlaybackProgress; - _sessionManager!.PlaybackStart -= OnPlaybackProgress; + _sessionManager.PlaybackProgress -= OnPlaybackProgress; + _sessionManager.PlaybackStart -= OnPlaybackProgress; } } } diff --git a/Jellyfin.Api/Models/StreamingDtos/StreamState.cs b/Jellyfin.Api/Models/StreamingDtos/StreamState.cs index 0f84faeafc..cbabf087bc 100644 --- a/Jellyfin.Api/Models/StreamingDtos/StreamState.cs +++ b/Jellyfin.Api/Models/StreamingDtos/StreamState.cs @@ -55,7 +55,7 @@ namespace Jellyfin.Api.Models.StreamingDtos /// /// Gets the video request. /// - public VideoRequestDto? VideoRequest => Request! as VideoRequestDto; + public VideoRequestDto? VideoRequest => Request as VideoRequestDto; /// /// Gets or sets the direct stream provicer. diff --git a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs index 244abf469e..ba2cfc724e 100644 --- a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs +++ b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs @@ -27,7 +27,7 @@ namespace Jellyfin.Server.Implementations.Security { if (requestContext.Request.HttpContext.Items.TryGetValue("AuthorizationInfo", out var cached) && cached != null) { - return Task.FromResult((AuthorizationInfo)cached!); // Cache should never contain null + return Task.FromResult((AuthorizationInfo)cached); // Cache should never contain null } return GetAuthorization(requestContext); -- cgit v1.2.3 From 017380f1ddccb46ce270f1d0df8e07d639ba3704 Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Mon, 4 Oct 2021 07:43:40 -0600 Subject: Reference dotnet6-rc1 packages --- Emby.Dlna/Emby.Dlna.csproj | 2 +- Emby.Server.Implementations/Emby.Server.Implementations.csproj | 10 +++++----- Jellyfin.Api/Jellyfin.Api.csproj | 4 ++-- Jellyfin.Data/Jellyfin.Data.csproj | 2 +- .../Jellyfin.Server.Implementations.csproj | 8 ++++---- .../Security/AuthorizationContext.cs | 2 +- Jellyfin.Server.Implementations/Users/UserManager.cs | 5 +++++ Jellyfin.Server/Jellyfin.Server.csproj | 8 ++++---- MediaBrowser.Common/MediaBrowser.Common.csproj | 4 ++-- MediaBrowser.Controller/MediaBrowser.Controller.csproj | 6 +++--- MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj | 4 ++-- MediaBrowser.Model/MediaBrowser.Model.csproj | 4 ++-- MediaBrowser.Providers/MediaBrowser.Providers.csproj | 6 +++--- tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 4 ++-- .../Jellyfin.Server.Integration.Tests.csproj | 6 +++--- tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj | 6 +++--- 16 files changed, 43 insertions(+), 38 deletions(-) (limited to 'Jellyfin.Server.Implementations/Security/AuthorizationContext.cs') diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index 1d4e3b047d..5348aed637 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -73,7 +73,7 @@ - + diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 428cad0715..fb19726104 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -25,11 +25,11 @@ - - - - - + + + + + diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 1c451ef6c1..f46c0cbd11 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -14,8 +14,8 @@ - - + + diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index 19aef704c0..f1bfaa63e0 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -35,7 +35,7 @@ - + diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index 337f5cb82a..d9e6d794b3 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -19,13 +19,13 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs index ba2cfc724e..3ab043c648 100644 --- a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs +++ b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs @@ -2,12 +2,12 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Net; using System.Threading.Tasks; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using Microsoft.AspNetCore.Http; +using Microsoft.EntityFrameworkCore; using Microsoft.Net.Http.Headers; namespace Jellyfin.Server.Implementations.Security diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index 02377bfd72..704a6a84ef 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -701,6 +701,11 @@ namespace Jellyfin.Server.Implementations.Users /// public async Task ClearProfileImageAsync(User user) { + if (user.ProfileImage == null) + { + return; + } + await using var dbContext = _dbProvider.CreateContext(); dbContext.Remove(user.ProfileImage); await dbContext.SaveChangesAsync().ConfigureAwait(false); diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 074d43fba8..6603105fa3 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -31,10 +31,10 @@ - - - - + + + + diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 6358c00001..c87d58a147 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -19,8 +19,8 @@ - - + + diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 47cec7d77f..997772c04c 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -15,10 +15,10 @@ - - + + - + diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 30cfb904e1..22bba23663 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -24,8 +24,8 @@ - - + + diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index b0a12a9c90..0ac58e3551 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -35,9 +35,9 @@ - + - + diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 29d6b01f23..71a3554fd6 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -16,9 +16,9 @@ - - - + + + diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index b52ea078af..8b581857fe 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -15,8 +15,8 @@ - - + + diff --git a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj index 7939c7118e..38687ae61a 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj +++ b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj @@ -9,14 +9,14 @@ - - + + - + diff --git a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj index b30e690a5e..db24df240c 100644 --- a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj +++ b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj @@ -10,13 +10,13 @@ - - + + - + -- cgit v1.2.3