using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Routing;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Xunit;
namespace IEvangelist.Tests
{
public class ActionTests
{
private const string RootNamespace = "[ Enter Root Namespace ]";
private const string Controller = nameof(Controller);
private const string WhiteListed = nameof(UnauthorizedActionInController.GetZero);
private static readonly Type ControllerType = typeof(Controller);
private static readonly string[] ExecutableExtensions = { ".exe", ".dll" };
public ActionTests()
{
LoadAllAssemblies();
}
private void LoadAllAssemblies()
{
var assemblies =
Directory.EnumerateFiles(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? string.Empty,
$"{RootNamespace}.*")
.Where(IsExeOrDll)
.Select(Assembly.LoadFrom)
.Select(assembly =>
TryCatchIgnore(() => AppDomain.CurrentDomain.Load(assembly.GetName())))
.ToList();
Assert.False(assemblies.IsNullOrEmpty());
}
[Fact]
public void AllActionsOrParentControllerHaveAuthorizationAttributeTest()
{
var allControllers = GetAllControllerTypes();
var unauthorizedControllers =
GetControllerTypesThatAreMissing<AuthorizeAttribute>(allControllers);
Assert.True(allControllers.Count > unauthorizedControllers.Count);
foreach (var controller in unauthorizedControllers)
{
var actions =
controller.GetMethods(BindingFlags.Public | BindingFlags.Instance)
.Where(m => m.GetCustomAttribute<HttpMethodAttribute>() != null)
.ToList();
var unauthorizedActions =
actions.Where(action => action.GetCustomAttribute<AuthorizeAttribute>() == null
&& action.GetCustomAttribute<AllowAnonymousAttribute>() == null)
.ToList();
if (unauthorizedActions.IsNullOrEmpty() ||
(unauthorizedActions.Count == 1 &&
unauthorizedActions[0].Name == WhiteListed))
{
continue;
}
unauthorizedActions.ForEach(action => Console.WriteLine($"{action} is unauthorized!"));
Assert.True(false, $"Unauthorized action found!");
}
}
private static List<Type> GetAllControllerTypes()
=> AppDomain.CurrentDomain
.GetAssemblies()
.Where(a => a.FullName.StartsWith(RootNamespace))
.SelectMany(a => a.GetTypes()
.Where(t => t.FullName.Contains(Controller) ||
t.BaseType == ControllerType ||
t.DeclaringType == ControllerType))
.ToList();
private static List<Type> GetControllerTypesThatAreMissing<TAttribute>(
IEnumerable<Type> types)
where TAttribute : Attribute
=> types.Where(t => t.GetCustomAttribute<TAttribute>() == null)
.ToList();
private static bool IsExeOrDll(string path)
=> ExecutableExtensions.Any(extension => extension.Equals(Path.GetExtension(path), StringComparison.OrdinalIgnoreCase));
private static T TryCatchIgnore<T>(Func<T> func)
{
try
{
return func();
}
catch { }
return default(T);
}
}
public class UnauthorizedTestController : Controller
{
}
public class UnauthorizedActionInController : Controller
{
[HttpGet]
public int GetZero() => 0;
[Authorize, HttpPost]
public IActionResult Post([FromBody] int number) => Ok();
[OverrideAge, HttpDelete]
public IActionResult Delete() => Ok();
}
public class OverrideAge : Authorize { }
}
Last active
March 22, 2018 21:41
-
-
Save IEvangelist/2023df7d43062169082b41c49fc54c9b to your computer and use it in GitHub Desktop.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment