1
0
Fork 0
mirror of https://github.com/Jackett/Jackett synced 2025-02-28 08:55:39 +00:00

Add Authorization

This commit is contained in:
flightlevel 2018-05-12 12:44:47 +10:00
parent 615794a4bf
commit ce84264490
8 changed files with 100 additions and 62 deletions

View file

@ -1,6 +1,7 @@
using Jackett.Common.Models.Config;
using Jackett.Common.Services.Interfaces;
using Jackett.Common.Utils;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using NLog;
@ -11,7 +12,7 @@ using System.Threading.Tasks;
namespace Jackett.Server.Controllers
{
//[AllowAnonymous]
[AllowAnonymous]
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
[Route("bh/{indexerID}")]
public class BlackholeController : Controller

View file

@ -2,6 +2,7 @@
using Jackett.Common.Models.Config;
using Jackett.Common.Services.Interfaces;
using Jackett.Common.Utils;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.WebUtilities;
using NLog;
@ -11,7 +12,7 @@ using System.Threading.Tasks;
namespace Jackett.Server.Controllers
{
//[AllowAnonymous]
[AllowAnonymous]
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
[Route("dl/{indexerID}")]
public class DownloadController : Controller

View file

@ -54,7 +54,6 @@ namespace Jackett.Server.Controllers
}
[Route("api/v2.0/indexers")]
//[JackettAuthorized]
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
public class IndexerApiController : Controller, IIndexerController
{

View file

@ -5,6 +5,7 @@ using Jackett.Common.Models;
using Jackett.Common.Models.DTO;
using Jackett.Common.Services.Interfaces;
using Jackett.Common.Utils;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using NLog;
@ -155,7 +156,7 @@ namespace Jackett.Server.Controllers
TorznabQuery CurrentQuery { get; set; }
}
//[AllowAnonymous]
[AllowAnonymous]
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
[Route("api/v2.0/indexers/{indexerId}/results")]
[TypeFilter(typeof(RequiresApiKey))]
@ -166,6 +167,9 @@ namespace Jackett.Server.Controllers
public IIndexerManagerService IndexerService { get; private set; }
public IIndexer CurrentIndexer { 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)
{
@ -481,8 +485,5 @@ namespace Jackett.Server.Controllers
}
}
private Logger logger;
private IServerService serverService;
private ICacheService cacheService;
}
}

View file

@ -12,7 +12,6 @@ using System.Linq;
namespace Jackett.Server.Controllers
{
[Route("api/v2.0/server/[action]")]
//[JackettAuthorized]
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
public class ServerConfigurationController : Controller
{

View file

@ -1,18 +1,19 @@
using Jackett.Common.Models.Config;
using Jackett.Common.Services.Interfaces;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MimeMapping;
using NLog;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
namespace Jackett.Server.Controllers
{
[Route("UI/[action]")]
//[JackettAuthorized]
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
public class WebUIController : Controller
{
@ -29,66 +30,76 @@ namespace Jackett.Server.Controllers
logger = l;
}
private HttpResponseMessage GetFile(string path)
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> Login()
{
var result = new HttpResponseMessage(HttpStatusCode.OK);
var mappedPath = Path.Combine(config.GetContentFolder(), path);
var stream = new FileStream(mappedPath, FileMode.Open, FileAccess.Read, FileShare.Read);
result.Content = new StreamContent(stream);
result.Content.Headers.ContentType = new MediaTypeHeaderValue(MimeUtility.GetMimeMapping(mappedPath));
if (string.IsNullOrEmpty(serverConfig.AdminPassword))
{
await MakeUserAuthenticated();
}
return result;
if (User.Identity.IsAuthenticated)
{
return Redirect("Dashboard");
}
return new PhysicalFileResult(config.GetContentFolder() + "/login.html", "text/html"); ;
}
[HttpGet]
//[AllowAnonymous]
public IActionResult Logout()
[AllowAnonymous]
public async Task<IActionResult> Logout()
{
var ctx = Request.HttpContext;
//TODO
//var authManager = ctx.Authentication;
//authManager.SignOut("ApplicationCookie");
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return Redirect("Login");
}
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> Dashboard([FromForm] string password)
{
if (password != null && securityService.HashPassword(password) == serverConfig.AdminPassword)
{
await MakeUserAuthenticated();
}
return Redirect("Dashboard");
}
[HttpGet]
[HttpPost]
//[AllowAnonymous]
public IActionResult Dashboard()
{
var result = new PhysicalFileResult(config.GetContentFolder() + "/index.html", "text/html");
return result;
bool logout = HttpContext.Request.Query.Where(x => String.Equals(x.Key, "logout", StringComparison.OrdinalIgnoreCase)
&& String.Equals(x.Value, "true", StringComparison.OrdinalIgnoreCase)).Any();
if (logout)
{
return Redirect("Logout");
}
//if (Request.Path != null && Request.Path.ToString().Contains("logout"))
//{
// var file = GetFile("login.html");
// securityService.Logout(file);
// return file;
//}
return new PhysicalFileResult(config.GetContentFolder() + "/index.html", "text/html");
}
//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))
//{
//return GetFile("index.html");
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
//}
//else
//{
// var formData = await Request.ReadFormAsync();
// if (formData != null && securityService.HashPassword(formData["password"]) == serverConfig.AdminPassword)
// {
// var file = GetFile("index.html");
// securityService.Login(file);
// return file;
// }
// else
// {
// return GetFile("login.html");
// }
//}
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
new AuthenticationProperties
{
ExpiresUtc = DateTime.UtcNow.AddMinutes(20),
IsPersistent = false,
AllowRefresh = true
});
}
}
}

View file

@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Rewrite;
using Microsoft.Net.Http.Headers;
using System;
namespace Jackett.Server.Middleware
{
@ -8,9 +9,10 @@ namespace Jackett.Server.Middleware
{
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
var redir = Initialisation.ServerService.BasePath() + "/UI/Dashboard";

View file

@ -5,8 +5,12 @@ using Jackett.Common.Plumbing;
using Jackett.Common.Services.Interfaces;
using Jackett.Server.Middleware;
using Jackett.Server.Services;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.AspNetCore.Rewrite;
using Microsoft.Extensions.Configuration;
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.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services
.AddMvc()
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver()); //Web app uses Pascal Case JSON
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,
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();
Configuration.GetSection("RuntimeSettings").Bind(runtimeSettings);
@ -77,6 +99,8 @@ namespace Jackett.Server
EnableDirectoryBrowsing = false
});
app.UseAuthentication();
app.UseMvc();
}
}