mirror of
https://github.com/Readarr/Readarr.git
synced 2026-04-04 19:15:33 -04:00
New: Use native dotnet host and DryIoc
This commit is contained in:
@@ -6,6 +6,7 @@ using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
||||
namespace Readarr.Http.Authentication
|
||||
{
|
||||
@@ -17,17 +18,20 @@ namespace Readarr.Http.Authentication
|
||||
|
||||
public string HeaderName { get; set; }
|
||||
public string QueryName { get; set; }
|
||||
public string ApiKey { get; set; }
|
||||
}
|
||||
|
||||
public class ApiKeyAuthenticationHandler : AuthenticationHandler<ApiKeyAuthenticationOptions>
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public ApiKeyAuthenticationHandler(IOptionsMonitor<ApiKeyAuthenticationOptions> options,
|
||||
ILoggerFactory logger,
|
||||
UrlEncoder encoder,
|
||||
ISystemClock clock)
|
||||
ISystemClock clock,
|
||||
IConfigFileProvider config)
|
||||
: base(options, logger, encoder, clock)
|
||||
{
|
||||
_apiKey = config.ApiKey;
|
||||
}
|
||||
|
||||
private string ParseApiKey()
|
||||
@@ -56,7 +60,7 @@ namespace Readarr.Http.Authentication
|
||||
return Task.FromResult(AuthenticateResult.NoResult());
|
||||
}
|
||||
|
||||
if (Options.ApiKey == providedApiKey)
|
||||
if (_apiKey == providedApiKey)
|
||||
{
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
|
||||
@@ -2,7 +2,6 @@ using System;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NzbDrone.Core.Authentication;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
||||
namespace Readarr.Http.Authentication
|
||||
{
|
||||
@@ -13,53 +12,37 @@ namespace Readarr.Http.Authentication
|
||||
return authenticationBuilder.AddScheme<ApiKeyAuthenticationOptions, ApiKeyAuthenticationHandler>(name, options);
|
||||
}
|
||||
|
||||
public static AuthenticationBuilder AddBasicAuthentication(this AuthenticationBuilder authenticationBuilder)
|
||||
public static AuthenticationBuilder AddBasic(this AuthenticationBuilder authenticationBuilder, string name)
|
||||
{
|
||||
return authenticationBuilder.AddScheme<AuthenticationSchemeOptions, BasicAuthenticationHandler>(AuthenticationType.Basic.ToString(), options => { });
|
||||
return authenticationBuilder.AddScheme<AuthenticationSchemeOptions, BasicAuthenticationHandler>(name, options => { });
|
||||
}
|
||||
|
||||
public static AuthenticationBuilder AddNoAuthentication(this AuthenticationBuilder authenticationBuilder)
|
||||
public static AuthenticationBuilder AddNone(this AuthenticationBuilder authenticationBuilder, string name)
|
||||
{
|
||||
return authenticationBuilder.AddScheme<AuthenticationSchemeOptions, NoAuthenticationHandler>(AuthenticationType.None.ToString(), options => { });
|
||||
return authenticationBuilder.AddScheme<AuthenticationSchemeOptions, NoAuthenticationHandler>(name, options => { });
|
||||
}
|
||||
|
||||
public static AuthenticationBuilder AddAppAuthentication(this IServiceCollection services, IConfigFileProvider config)
|
||||
public static AuthenticationBuilder AddAppAuthentication(this IServiceCollection services)
|
||||
{
|
||||
var authBuilder = services.AddAuthentication(config.AuthenticationMethod.ToString());
|
||||
|
||||
if (config.AuthenticationMethod == AuthenticationType.Basic)
|
||||
{
|
||||
authBuilder.AddBasicAuthentication();
|
||||
}
|
||||
else if (config.AuthenticationMethod == AuthenticationType.Forms)
|
||||
{
|
||||
authBuilder.AddCookie(AuthenticationType.Forms.ToString(), options =>
|
||||
return services.AddAuthentication()
|
||||
.AddNone(AuthenticationType.None.ToString())
|
||||
.AddBasic(AuthenticationType.Basic.ToString())
|
||||
.AddCookie(AuthenticationType.Forms.ToString(), options =>
|
||||
{
|
||||
options.AccessDeniedPath = "/login?loginFailed=true";
|
||||
options.LoginPath = "/login";
|
||||
options.ExpireTimeSpan = TimeSpan.FromDays(7);
|
||||
})
|
||||
.AddApiKey("API", options =>
|
||||
{
|
||||
options.HeaderName = "X-Api-Key";
|
||||
options.QueryName = "apikey";
|
||||
})
|
||||
.AddApiKey("SignalR", options =>
|
||||
{
|
||||
options.HeaderName = "X-Api-Key";
|
||||
options.QueryName = "access_token";
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
authBuilder.AddNoAuthentication();
|
||||
}
|
||||
|
||||
authBuilder.AddApiKey("API", options =>
|
||||
{
|
||||
options.HeaderName = "X-Api-Key";
|
||||
options.QueryName = "apikey";
|
||||
options.ApiKey = config.ApiKey;
|
||||
});
|
||||
|
||||
authBuilder.AddApiKey("SignalR", options =>
|
||||
{
|
||||
options.HeaderName = "X-Api-Key";
|
||||
options.QueryName = "access_token";
|
||||
options.ApiKey = config.ApiKey;
|
||||
});
|
||||
|
||||
return authBuilder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NzbDrone.Core.Authentication;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
||||
namespace Readarr.Http.Authentication
|
||||
@@ -35,14 +36,14 @@ namespace Readarr.Http.Authentication
|
||||
{
|
||||
new Claim("user", user.Username),
|
||||
new Claim("identifier", user.Identifier.ToString()),
|
||||
new Claim("UiAuth", "true")
|
||||
new Claim("AuthType", AuthenticationType.Forms.ToString())
|
||||
};
|
||||
|
||||
var authProperties = new AuthenticationProperties
|
||||
{
|
||||
IsPersistent = resource.RememberMe == "on"
|
||||
};
|
||||
await HttpContext.SignInAsync(new ClaimsPrincipal(new ClaimsIdentity(claims, "Cookies", "user", "identifier")), authProperties);
|
||||
await HttpContext.SignInAsync(AuthenticationType.Forms.ToString(), new ClaimsPrincipal(new ClaimsIdentity(claims, "Cookies", "user", "identifier")), authProperties);
|
||||
|
||||
return Redirect("/");
|
||||
}
|
||||
@@ -51,7 +52,7 @@ namespace Readarr.Http.Authentication
|
||||
public async Task<IActionResult> Logout()
|
||||
{
|
||||
_authService.Logout(HttpContext);
|
||||
await HttpContext.SignOutAsync();
|
||||
await HttpContext.SignOutAsync(AuthenticationType.Forms.ToString());
|
||||
return Redirect("/");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Core.Authentication;
|
||||
|
||||
namespace Readarr.Http.Authentication
|
||||
{
|
||||
@@ -58,7 +59,7 @@ namespace Readarr.Http.Authentication
|
||||
{
|
||||
new Claim("user", user.Username),
|
||||
new Claim("identifier", user.Identifier.ToString()),
|
||||
new Claim("UiAuth", "true")
|
||||
new Claim("AuthType", AuthenticationType.Basic.ToString())
|
||||
};
|
||||
|
||||
var identity = new ClaimsIdentity(claims, "Basic", "user", "identifier");
|
||||
|
||||
@@ -5,13 +5,13 @@ using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using NzbDrone.Core.Authentication;
|
||||
|
||||
namespace Readarr.Http.Authentication
|
||||
{
|
||||
public class NoAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
|
||||
{
|
||||
public NoAuthenticationHandler(IAuthenticationService authService,
|
||||
IOptionsMonitor<AuthenticationSchemeOptions> options,
|
||||
public NoAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options,
|
||||
ILoggerFactory logger,
|
||||
UrlEncoder encoder,
|
||||
ISystemClock clock)
|
||||
@@ -24,7 +24,7 @@ namespace Readarr.Http.Authentication
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new Claim("user", "Anonymous"),
|
||||
new Claim("UiAuth", "true")
|
||||
new Claim("AuthType", AuthenticationType.None.ToString())
|
||||
};
|
||||
|
||||
var identity = new ClaimsIdentity(claims, "NoAuth", "user", "identifier");
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.Extensions.Options;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
||||
namespace NzbDrone.Http.Authentication
|
||||
{
|
||||
public class UiAuthorizationPolicyProvider : IAuthorizationPolicyProvider
|
||||
{
|
||||
private const string POLICY_NAME = "UI";
|
||||
private readonly IConfigFileProvider _config;
|
||||
|
||||
public DefaultAuthorizationPolicyProvider FallbackPolicyProvider { get; }
|
||||
|
||||
public UiAuthorizationPolicyProvider(IOptions<AuthorizationOptions> options,
|
||||
IConfigFileProvider config)
|
||||
{
|
||||
FallbackPolicyProvider = new DefaultAuthorizationPolicyProvider(options);
|
||||
_config = config;
|
||||
}
|
||||
|
||||
public Task<AuthorizationPolicy> GetDefaultPolicyAsync() => FallbackPolicyProvider.GetDefaultPolicyAsync();
|
||||
|
||||
public Task<AuthorizationPolicy> GetFallbackPolicyAsync() => FallbackPolicyProvider.GetFallbackPolicyAsync();
|
||||
|
||||
public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
|
||||
{
|
||||
if (policyName.Equals(POLICY_NAME, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var policy = new AuthorizationPolicyBuilder(_config.AuthenticationMethod.ToString())
|
||||
.RequireAuthenticatedUser();
|
||||
return Task.FromResult(policy.Build());
|
||||
}
|
||||
|
||||
return FallbackPolicyProvider.GetPolicyAsync(policyName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,13 +10,13 @@ namespace Readarr.Http.Frontend.Mappers
|
||||
public abstract class HtmlMapperBase : StaticResourceMapperBase
|
||||
{
|
||||
private readonly IDiskProvider _diskProvider;
|
||||
private readonly Func<ICacheBreakerProvider> _cacheBreakProviderFactory;
|
||||
private readonly Lazy<ICacheBreakerProvider> _cacheBreakProviderFactory;
|
||||
private static readonly Regex ReplaceRegex = new Regex(@"(?:(?<attribute>href|src)=\"")(?<path>.*?(?<extension>css|js|png|ico|ics|svg|json))(?:\"")(?:\s(?<nohash>data-no-hash))?", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
private string _generatedContent;
|
||||
|
||||
protected HtmlMapperBase(IDiskProvider diskProvider,
|
||||
Func<ICacheBreakerProvider> cacheBreakProviderFactory,
|
||||
Lazy<ICacheBreakerProvider> cacheBreakProviderFactory,
|
||||
Logger logger)
|
||||
: base(diskProvider, logger)
|
||||
{
|
||||
@@ -56,7 +56,7 @@ namespace Readarr.Http.Frontend.Mappers
|
||||
}
|
||||
|
||||
var text = _diskProvider.ReadAllText(HtmlPath);
|
||||
var cacheBreakProvider = _cacheBreakProviderFactory();
|
||||
var cacheBreakProvider = _cacheBreakProviderFactory.Value;
|
||||
|
||||
text = ReplaceRegex.Replace(text, match =>
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Readarr.Http.Frontend.Mappers
|
||||
public IndexHtmlMapper(IAppFolderInfo appFolderInfo,
|
||||
IDiskProvider diskProvider,
|
||||
IConfigFileProvider configFileProvider,
|
||||
Func<ICacheBreakerProvider> cacheBreakProviderFactory,
|
||||
Lazy<ICacheBreakerProvider> cacheBreakProviderFactory,
|
||||
Logger logger)
|
||||
: base(diskProvider, cacheBreakProviderFactory, logger)
|
||||
{
|
||||
|
||||
30
src/Readarr.Http/Middleware/BufferingMiddleware.cs
Normal file
30
src/Readarr.Http/Middleware/BufferingMiddleware.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Readarr.Http.Middleware
|
||||
{
|
||||
public class BufferingMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly List<string> _urls;
|
||||
|
||||
public BufferingMiddleware(RequestDelegate next, List<string> urls)
|
||||
{
|
||||
_next = next;
|
||||
_urls = urls;
|
||||
}
|
||||
|
||||
public async Task InvokeAsync(HttpContext context)
|
||||
{
|
||||
if (_urls.Any(p => context.Request.Path.StartsWithSegments(p, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
context.Request.EnableBuffering();
|
||||
}
|
||||
|
||||
await _next(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user