mirror of
https://github.com/Readarr/Readarr.git
synced 2026-04-20 21:54:25 -04:00
New: Use ASP.NET Core instead of Nancy
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Http.REST.Attributes;
|
||||
using Readarr.Http.Validation;
|
||||
|
||||
namespace Readarr.Http.REST
|
||||
{
|
||||
public abstract class RestController<TResource> : Controller
|
||||
where TResource : RestResource, new()
|
||||
{
|
||||
private static readonly List<Type> VALIDATE_ID_ATTRIBUTES = new List<Type> { typeof(RestPutByIdAttribute), typeof(RestDeleteByIdAttribute) };
|
||||
|
||||
protected ResourceValidator<TResource> PostValidator { get; private set; }
|
||||
protected ResourceValidator<TResource> PutValidator { get; private set; }
|
||||
protected ResourceValidator<TResource> SharedValidator { get; private set; }
|
||||
|
||||
protected void ValidateId(int id)
|
||||
{
|
||||
if (id <= 0)
|
||||
{
|
||||
throw new BadRequestException(id + " is not a valid ID");
|
||||
}
|
||||
}
|
||||
|
||||
protected RestController()
|
||||
{
|
||||
PostValidator = new ResourceValidator<TResource>();
|
||||
PutValidator = new ResourceValidator<TResource>();
|
||||
SharedValidator = new ResourceValidator<TResource>();
|
||||
|
||||
PutValidator.RuleFor(r => r.Id).ValidId();
|
||||
}
|
||||
|
||||
[RestGetById]
|
||||
public abstract TResource GetResourceById(int id);
|
||||
|
||||
public override void OnActionExecuting(ActionExecutingContext context)
|
||||
{
|
||||
var descriptor = context.ActionDescriptor as ControllerActionDescriptor;
|
||||
|
||||
var skipAttribute = (SkipValidationAttribute)Attribute.GetCustomAttribute(descriptor.MethodInfo, typeof(SkipValidationAttribute), true);
|
||||
var skipValidate = skipAttribute?.Skip ?? false;
|
||||
var skipShared = skipAttribute?.SkipShared ?? false;
|
||||
|
||||
if (Request.Method == "POST" || Request.Method == "PUT")
|
||||
{
|
||||
var resourceArgs = context.ActionArguments.Values.Where(x => x.GetType() == typeof(TResource))
|
||||
.Select(x => x as TResource)
|
||||
.ToList();
|
||||
|
||||
foreach (var resource in resourceArgs)
|
||||
{
|
||||
ValidateResource(resource, skipValidate, skipShared);
|
||||
}
|
||||
}
|
||||
|
||||
var attributes = descriptor.MethodInfo.CustomAttributes;
|
||||
if (attributes.Any(x => VALIDATE_ID_ATTRIBUTES.Contains(x.GetType())) && !skipValidate)
|
||||
{
|
||||
if (context.ActionArguments.TryGetValue("id", out var idObj))
|
||||
{
|
||||
ValidateId((int)idObj);
|
||||
}
|
||||
}
|
||||
|
||||
base.OnActionExecuting(context);
|
||||
}
|
||||
|
||||
public override void OnActionExecuted(ActionExecutedContext context)
|
||||
{
|
||||
var descriptor = context.ActionDescriptor as ControllerActionDescriptor;
|
||||
|
||||
var attributes = descriptor.MethodInfo.CustomAttributes;
|
||||
|
||||
if (context.Exception?.GetType() == typeof(ModelNotFoundException) &&
|
||||
attributes.Any(x => x.AttributeType == typeof(RestGetByIdAttribute)))
|
||||
{
|
||||
context.Result = new NotFoundResult();
|
||||
}
|
||||
}
|
||||
|
||||
protected void ValidateResource(TResource resource, bool skipValidate = false, bool skipSharedValidate = false)
|
||||
{
|
||||
if (resource == null)
|
||||
{
|
||||
throw new BadRequestException("Request body can't be empty");
|
||||
}
|
||||
|
||||
var errors = new List<ValidationFailure>();
|
||||
|
||||
if (!skipSharedValidate)
|
||||
{
|
||||
errors.AddRange(SharedValidator.Validate(resource).Errors);
|
||||
}
|
||||
|
||||
if (Request.Method.Equals("POST", StringComparison.InvariantCultureIgnoreCase) && !skipValidate && !Request.Path.ToString().EndsWith("/test", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
errors.AddRange(PostValidator.Validate(resource).Errors);
|
||||
}
|
||||
else if (Request.Method.Equals("PUT", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
errors.AddRange(PutValidator.Validate(resource).Errors);
|
||||
}
|
||||
|
||||
if (errors.Any())
|
||||
{
|
||||
throw new ValidationException(errors);
|
||||
}
|
||||
}
|
||||
|
||||
protected ActionResult<TResource> Accepted(int id)
|
||||
{
|
||||
var result = GetResourceById(id);
|
||||
return AcceptedAtAction(nameof(GetResourceById), new { id = id }, result);
|
||||
}
|
||||
|
||||
protected ActionResult<TResource> Created(int id)
|
||||
{
|
||||
var result = GetResourceById(id);
|
||||
return CreatedAtAction(nameof(GetResourceById), new { id = id }, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user