mirror of
https://github.com/Jackett/Jackett
synced 2025-02-28 17:05:40 +00:00
Add Authorization
This commit is contained in:
parent
615794a4bf
commit
ce84264490
8 changed files with 100 additions and 62 deletions
|
@ -1,6 +1,7 @@
|
||||||
using Jackett.Common.Models.Config;
|
using Jackett.Common.Models.Config;
|
||||||
using Jackett.Common.Services.Interfaces;
|
using Jackett.Common.Services.Interfaces;
|
||||||
using Jackett.Common.Utils;
|
using Jackett.Common.Utils;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
@ -11,7 +12,7 @@ using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Jackett.Server.Controllers
|
namespace Jackett.Server.Controllers
|
||||||
{
|
{
|
||||||
//[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
|
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
|
||||||
[Route("bh/{indexerID}")]
|
[Route("bh/{indexerID}")]
|
||||||
public class BlackholeController : Controller
|
public class BlackholeController : Controller
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using Jackett.Common.Models.Config;
|
using Jackett.Common.Models.Config;
|
||||||
using Jackett.Common.Services.Interfaces;
|
using Jackett.Common.Services.Interfaces;
|
||||||
using Jackett.Common.Utils;
|
using Jackett.Common.Utils;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.WebUtilities;
|
using Microsoft.AspNetCore.WebUtilities;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
@ -11,7 +12,7 @@ using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Jackett.Server.Controllers
|
namespace Jackett.Server.Controllers
|
||||||
{
|
{
|
||||||
//[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
|
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
|
||||||
[Route("dl/{indexerID}")]
|
[Route("dl/{indexerID}")]
|
||||||
public class DownloadController : Controller
|
public class DownloadController : Controller
|
||||||
|
|
|
@ -54,7 +54,6 @@ namespace Jackett.Server.Controllers
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("api/v2.0/indexers")]
|
[Route("api/v2.0/indexers")]
|
||||||
//[JackettAuthorized]
|
|
||||||
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
|
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
|
||||||
public class IndexerApiController : Controller, IIndexerController
|
public class IndexerApiController : Controller, IIndexerController
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,6 +5,7 @@ using Jackett.Common.Models;
|
||||||
using Jackett.Common.Models.DTO;
|
using Jackett.Common.Models.DTO;
|
||||||
using Jackett.Common.Services.Interfaces;
|
using Jackett.Common.Services.Interfaces;
|
||||||
using Jackett.Common.Utils;
|
using Jackett.Common.Utils;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
@ -155,7 +156,7 @@ namespace Jackett.Server.Controllers
|
||||||
TorznabQuery CurrentQuery { get; set; }
|
TorznabQuery CurrentQuery { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
//[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
|
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
|
||||||
[Route("api/v2.0/indexers/{indexerId}/results")]
|
[Route("api/v2.0/indexers/{indexerId}/results")]
|
||||||
[TypeFilter(typeof(RequiresApiKey))]
|
[TypeFilter(typeof(RequiresApiKey))]
|
||||||
|
@ -166,6 +167,9 @@ namespace Jackett.Server.Controllers
|
||||||
public IIndexerManagerService IndexerService { get; private set; }
|
public IIndexerManagerService IndexerService { get; private set; }
|
||||||
public IIndexer CurrentIndexer { get; set; }
|
public IIndexer CurrentIndexer { get; set; }
|
||||||
public TorznabQuery CurrentQuery { get; set; }
|
public TorznabQuery CurrentQuery { get; set; }
|
||||||
|
private Logger logger;
|
||||||
|
private IServerService serverService;
|
||||||
|
private ICacheService cacheService;
|
||||||
|
|
||||||
public ResultsController(IIndexerManagerService indexerManagerService, IServerService ss, ICacheService c, Logger logger)
|
public ResultsController(IIndexerManagerService indexerManagerService, IServerService ss, ICacheService c, Logger logger)
|
||||||
{
|
{
|
||||||
|
@ -481,8 +485,5 @@ namespace Jackett.Server.Controllers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Logger logger;
|
|
||||||
private IServerService serverService;
|
|
||||||
private ICacheService cacheService;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@ using System.Linq;
|
||||||
namespace Jackett.Server.Controllers
|
namespace Jackett.Server.Controllers
|
||||||
{
|
{
|
||||||
[Route("api/v2.0/server/[action]")]
|
[Route("api/v2.0/server/[action]")]
|
||||||
//[JackettAuthorized]
|
|
||||||
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
|
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
|
||||||
public class ServerConfigurationController : Controller
|
public class ServerConfigurationController : Controller
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
using Jackett.Common.Models.Config;
|
using Jackett.Common.Models.Config;
|
||||||
using Jackett.Common.Services.Interfaces;
|
using Jackett.Common.Services.Interfaces;
|
||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using MimeMapping;
|
|
||||||
using NLog;
|
using NLog;
|
||||||
using System.IO;
|
using System;
|
||||||
using System.Net;
|
using System.Collections.Generic;
|
||||||
using System.Net.Http;
|
using System.Linq;
|
||||||
using System.Net.Http.Headers;
|
using System.Security.Claims;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Jackett.Server.Controllers
|
namespace Jackett.Server.Controllers
|
||||||
{
|
{
|
||||||
[Route("UI/[action]")]
|
[Route("UI/[action]")]
|
||||||
//[JackettAuthorized]
|
|
||||||
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
|
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
|
||||||
public class WebUIController : Controller
|
public class WebUIController : Controller
|
||||||
{
|
{
|
||||||
|
@ -29,66 +30,76 @@ namespace Jackett.Server.Controllers
|
||||||
logger = l;
|
logger = l;
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpResponseMessage GetFile(string path)
|
[HttpGet]
|
||||||
|
[AllowAnonymous]
|
||||||
|
public async Task<IActionResult> Login()
|
||||||
{
|
{
|
||||||
var result = new HttpResponseMessage(HttpStatusCode.OK);
|
if (string.IsNullOrEmpty(serverConfig.AdminPassword))
|
||||||
var mappedPath = Path.Combine(config.GetContentFolder(), path);
|
{
|
||||||
var stream = new FileStream(mappedPath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
await MakeUserAuthenticated();
|
||||||
result.Content = new StreamContent(stream);
|
}
|
||||||
result.Content.Headers.ContentType = new MediaTypeHeaderValue(MimeUtility.GetMimeMapping(mappedPath));
|
|
||||||
|
|
||||||
return result;
|
if (User.Identity.IsAuthenticated)
|
||||||
|
{
|
||||||
|
return Redirect("Dashboard");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PhysicalFileResult(config.GetContentFolder() + "/login.html", "text/html"); ;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
//[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
public IActionResult Logout()
|
public async Task<IActionResult> Logout()
|
||||||
{
|
{
|
||||||
var ctx = Request.HttpContext;
|
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||||
//TODO
|
return Redirect("Login");
|
||||||
//var authManager = ctx.Authentication;
|
}
|
||||||
//authManager.SignOut("ApplicationCookie");
|
|
||||||
|
[HttpPost]
|
||||||
|
[AllowAnonymous]
|
||||||
|
public async Task<IActionResult> Dashboard([FromForm] string password)
|
||||||
|
{
|
||||||
|
if (password != null && securityService.HashPassword(password) == serverConfig.AdminPassword)
|
||||||
|
{
|
||||||
|
await MakeUserAuthenticated();
|
||||||
|
}
|
||||||
|
|
||||||
return Redirect("Dashboard");
|
return Redirect("Dashboard");
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[HttpPost]
|
|
||||||
//[AllowAnonymous]
|
|
||||||
public IActionResult Dashboard()
|
public IActionResult Dashboard()
|
||||||
{
|
{
|
||||||
var result = new PhysicalFileResult(config.GetContentFolder() + "/index.html", "text/html");
|
bool logout = HttpContext.Request.Query.Where(x => String.Equals(x.Key, "logout", StringComparison.OrdinalIgnoreCase)
|
||||||
return result;
|
&& String.Equals(x.Value, "true", StringComparison.OrdinalIgnoreCase)).Any();
|
||||||
|
|
||||||
|
if (logout)
|
||||||
|
{
|
||||||
|
return Redirect("Logout");
|
||||||
|
}
|
||||||
|
|
||||||
//if (Request.Path != null && Request.Path.ToString().Contains("logout"))
|
return new PhysicalFileResult(config.GetContentFolder() + "/index.html", "text/html");
|
||||||
//{
|
}
|
||||||
// var file = GetFile("login.html");
|
|
||||||
// securityService.Logout(file);
|
|
||||||
// return file;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//TODO
|
//TODO: Move this to security service once off Mono
|
||||||
|
private async Task MakeUserAuthenticated()
|
||||||
|
{
|
||||||
|
var claims = new List<Claim>
|
||||||
|
{
|
||||||
|
new Claim(ClaimTypes.Name, "Jackett", ClaimValueTypes.String)
|
||||||
|
};
|
||||||
|
|
||||||
//if (securityService.CheckAuthorised(Request))
|
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
|
||||||
//{
|
|
||||||
//return GetFile("index.html");
|
|
||||||
|
|
||||||
//}
|
await HttpContext.SignInAsync(
|
||||||
//else
|
CookieAuthenticationDefaults.AuthenticationScheme,
|
||||||
//{
|
new ClaimsPrincipal(claimsIdentity),
|
||||||
// var formData = await Request.ReadFormAsync();
|
new AuthenticationProperties
|
||||||
|
{
|
||||||
// if (formData != null && securityService.HashPassword(formData["password"]) == serverConfig.AdminPassword)
|
ExpiresUtc = DateTime.UtcNow.AddMinutes(20),
|
||||||
// {
|
IsPersistent = false,
|
||||||
// var file = GetFile("index.html");
|
AllowRefresh = true
|
||||||
// securityService.Login(file);
|
});
|
||||||
// return file;
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// return GetFile("login.html");
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Rewrite;
|
using Microsoft.AspNetCore.Rewrite;
|
||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Jackett.Server.Middleware
|
namespace Jackett.Server.Middleware
|
||||||
{
|
{
|
||||||
|
@ -8,9 +9,10 @@ namespace Jackett.Server.Middleware
|
||||||
{
|
{
|
||||||
public static void RedirectToDashboard(RewriteContext context)
|
public static void RedirectToDashboard(RewriteContext context)
|
||||||
{
|
{
|
||||||
var request = context.HttpContext.Request;
|
HttpRequest request = context.HttpContext.Request;
|
||||||
|
|
||||||
if (request.Path == null || string.IsNullOrWhiteSpace(request.Path.ToString()) || request.Path.ToString() == "/")
|
if (request.Path == null || string.IsNullOrWhiteSpace(request.Path.ToString()) || request.Path.ToString() == "/"
|
||||||
|
|| request.Path.ToString().Equals("/index.html", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
// 301 is the status code of permanent redirect
|
// 301 is the status code of permanent redirect
|
||||||
var redir = Initialisation.ServerService.BasePath() + "/UI/Dashboard";
|
var redir = Initialisation.ServerService.BasePath() + "/UI/Dashboard";
|
||||||
|
|
|
@ -5,8 +5,12 @@ using Jackett.Common.Plumbing;
|
||||||
using Jackett.Common.Services.Interfaces;
|
using Jackett.Common.Services.Interfaces;
|
||||||
using Jackett.Server.Middleware;
|
using Jackett.Server.Middleware;
|
||||||
using Jackett.Server.Services;
|
using Jackett.Server.Services;
|
||||||
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Authorization;
|
||||||
using Microsoft.AspNetCore.Rewrite;
|
using Microsoft.AspNetCore.Rewrite;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
@ -29,9 +33,27 @@ namespace Jackett.Server
|
||||||
// This method gets called by the runtime. Use this method to add services to the container.
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
public IServiceProvider ConfigureServices(IServiceCollection services)
|
public IServiceProvider ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
services
|
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
|
||||||
.AddMvc()
|
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,
|
||||||
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver()); //Web app uses Pascal Case JSON
|
options =>
|
||||||
|
{
|
||||||
|
options.LoginPath = new PathString("/UI/Login");
|
||||||
|
options.AccessDeniedPath = new PathString("/UI/Login");
|
||||||
|
options.LogoutPath = new PathString("/UI/Logout");
|
||||||
|
options.Cookie.Name = "Jackett";
|
||||||
|
});
|
||||||
|
|
||||||
|
services.AddMvc(config =>
|
||||||
|
{
|
||||||
|
var policy = new AuthorizationPolicyBuilder()
|
||||||
|
.RequireAuthenticatedUser()
|
||||||
|
.Build();
|
||||||
|
config.Filters.Add(new AuthorizeFilter(policy));
|
||||||
|
})
|
||||||
|
.AddJsonOptions(options =>
|
||||||
|
{
|
||||||
|
options.SerializerSettings.ContractResolver = new DefaultContractResolver(); //Web app uses Pascal Case JSON
|
||||||
|
});
|
||||||
|
|
||||||
RuntimeSettings runtimeSettings = new RuntimeSettings();
|
RuntimeSettings runtimeSettings = new RuntimeSettings();
|
||||||
Configuration.GetSection("RuntimeSettings").Bind(runtimeSettings);
|
Configuration.GetSection("RuntimeSettings").Bind(runtimeSettings);
|
||||||
|
@ -77,6 +99,8 @@ namespace Jackett.Server
|
||||||
EnableDirectoryBrowsing = false
|
EnableDirectoryBrowsing = false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.UseAuthentication();
|
||||||
|
|
||||||
app.UseMvc();
|
app.UseMvc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue