diff --git a/dependencies.props b/dependencies.props
index fe0615c..cb965a6 100644
--- a/dependencies.props
+++ b/dependencies.props
@@ -13,6 +13,8 @@
1.0.7
2.2.1
1.2.0
+ 1.0.1
1.0.1
+ 4.2.2
\ No newline at end of file
diff --git a/src/api/NetworkResurrector.Api.Application/DependencyInjectionExtensions.cs b/src/api/NetworkResurrector.Api.Application/DependencyInjectionExtensions.cs
index 8d235f9..dfc82a3 100644
--- a/src/api/NetworkResurrector.Api.Application/DependencyInjectionExtensions.cs
+++ b/src/api/NetworkResurrector.Api.Application/DependencyInjectionExtensions.cs
@@ -1,6 +1,7 @@
using Microsoft.Extensions.DependencyInjection;
using NetworkResurrector.Api.Application.Services;
using NetworkResurrector.Api.Application.Services.Abstractions;
+using NetworkResurrector.Api.Application.Services.Decorators;
namespace NetworkResurrector.Api.Application
{
@@ -9,6 +10,8 @@ namespace NetworkResurrector.Api.Application
public static void AddApplicationServices(this IServiceCollection services)
{
services.AddSingleton();
+ services.AddScoped();
+ services.Decorate();
}
}
}
diff --git a/src/api/NetworkResurrector.Api.Application/NetworkResurrector.Api.Application.csproj b/src/api/NetworkResurrector.Api.Application/NetworkResurrector.Api.Application.csproj
index 0a0c3a2..e14826d 100644
--- a/src/api/NetworkResurrector.Api.Application/NetworkResurrector.Api.Application.csproj
+++ b/src/api/NetworkResurrector.Api.Application/NetworkResurrector.Api.Application.csproj
@@ -11,10 +11,12 @@
+
+
diff --git a/src/api/NetworkResurrector.Api.Application/Queries/GetUserPermissions.cs b/src/api/NetworkResurrector.Api.Application/Queries/GetUserPermissions.cs
index 227967b..4196532 100644
--- a/src/api/NetworkResurrector.Api.Application/Queries/GetUserPermissions.cs
+++ b/src/api/NetworkResurrector.Api.Application/Queries/GetUserPermissions.cs
@@ -1,5 +1,6 @@
using MediatR;
using Netmash.Security.Authentication.Tuitio.Abstractions;
+using NetworkResurrector.Api.Application.Services.Abstractions;
using NetworkResurrector.Api.Domain.Repositories;
using System.Collections.Generic;
using System.Linq;
@@ -19,19 +20,16 @@ namespace NetworkResurrector.Api.Application.Queries
public class QueryHandler : IRequestHandler
{
- private readonly IUserContextAccessor _userContext;
- private readonly ISecurityRepository _securityRepository;
+ private readonly IUserContext _userContext;
- public QueryHandler(IUserContextAccessor userContext, ISecurityRepository securityRepository)
+ public QueryHandler(IUserContext userContext)
{
_userContext=userContext;
- _securityRepository=securityRepository;
}
public async Task Handle(Query request, CancellationToken cancellationToken)
{
- var roles = _userContext.UserRoles.Select(r => r.id);
- var permissions = await _securityRepository.GetUserPermissionCodes(roles);
+ var permissions = await _userContext.GetUserPermissions();
return new Model()
{
Permissions = permissions
diff --git a/src/api/NetworkResurrector.Api.Application/Services/Abstractions/IUserContext.cs b/src/api/NetworkResurrector.Api.Application/Services/Abstractions/IUserContext.cs
new file mode 100644
index 0000000..52e0582
--- /dev/null
+++ b/src/api/NetworkResurrector.Api.Application/Services/Abstractions/IUserContext.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace NetworkResurrector.Api.Application.Services.Abstractions
+{
+ public interface IUserContext
+ {
+ Task> GetUserPermissions();
+ }
+}
diff --git a/src/api/NetworkResurrector.Api.Application/Services/Decorators/UserContextCache.cs b/src/api/NetworkResurrector.Api.Application/Services/Decorators/UserContextCache.cs
new file mode 100644
index 0000000..b8c2147
--- /dev/null
+++ b/src/api/NetworkResurrector.Api.Application/Services/Decorators/UserContextCache.cs
@@ -0,0 +1,35 @@
+using Netmash.Extensions.Caching.Services;
+using Netmash.Security.Authentication.Tuitio.Abstractions;
+using NetworkResurrector.Api.Application.Services.Abstractions;
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace NetworkResurrector.Api.Application.Services.Decorators
+{
+ internal class UserContextCache : IUserContext
+ {
+ private readonly IUserContextAccessor _userContextAccessor;
+ private readonly IUserContext _inner;
+ private readonly ICacheService _cache;
+
+ public UserContextCache(IUserContextAccessor userContextAccessor, IUserContext inner, ICacheService cache)
+ {
+ _userContextAccessor=userContextAccessor;
+ _inner=inner;
+ _cache=cache;
+ }
+
+ public async Task> GetUserPermissions()
+ {
+ var key = $"UserPermissions_{_userContextAccessor.UserId}";
+ var result = await _cache.GetAsync>(key);
+ if (result == null)
+ {
+ result = await _inner.GetUserPermissions();
+ await _cache.SetAsync(key, result);
+ }
+ return result;
+ }
+ }
+}
diff --git a/src/api/NetworkResurrector.Api.Application/Services/UserContext.cs b/src/api/NetworkResurrector.Api.Application/Services/UserContext.cs
new file mode 100644
index 0000000..0e682ed
--- /dev/null
+++ b/src/api/NetworkResurrector.Api.Application/Services/UserContext.cs
@@ -0,0 +1,28 @@
+using Netmash.Security.Authentication.Tuitio.Abstractions;
+using NetworkResurrector.Api.Application.Services.Abstractions;
+using NetworkResurrector.Api.Domain.Repositories;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace NetworkResurrector.Api.Application.Services
+{
+ internal class UserContext : IUserContext
+ {
+ private readonly IUserContextAccessor _userContext;
+ private readonly ISecurityRepository _securityRepository;
+
+ public UserContext(IUserContextAccessor userContext, ISecurityRepository securityRepository)
+ {
+ _userContext=userContext;
+ _securityRepository=securityRepository;
+ }
+
+ public async Task> GetUserPermissions()
+ {
+ var roles = _userContext.UserRoles.Select(r => r.id);
+ var permissions = await _securityRepository.GetUserPermissionCodes(roles);
+ return permissions;
+ }
+ }
+}
diff --git a/src/api/NetworkResurrector.Api.Domain/Constants/PermissionCodes.cs b/src/api/NetworkResurrector.Api.Domain/Constants/PermissionCodes.cs
new file mode 100644
index 0000000..c1a46b6
--- /dev/null
+++ b/src/api/NetworkResurrector.Api.Domain/Constants/PermissionCodes.cs
@@ -0,0 +1,14 @@
+namespace NetworkResurrector.Api.Domain.Constants
+{
+ public struct PermissionCodes
+ {
+ public const string
+ VIEW_DASHBOARD = "VIEW_DASHBOARD",
+ MANAGE_USERS = "MANAGE_USERS",
+ MANAGE_SETTINGS = "MANAGE_SETTINGS",
+ VIEW_MACHINES = "VIEW_MACHINES",
+ MANAGE_MACHINES = "MANAGE_MACHINES",
+ OPERATE_MACHINES = "OPERATE_MACHINES",
+ GUEST_ACCESS = "GUEST_ACCESS";
+ }
+}
diff --git a/src/api/NetworkResurrector.Api/Authorization/Constants/Policies.cs b/src/api/NetworkResurrector.Api/Authorization/Constants/Policies.cs
new file mode 100644
index 0000000..3d03d93
--- /dev/null
+++ b/src/api/NetworkResurrector.Api/Authorization/Constants/Policies.cs
@@ -0,0 +1,8 @@
+namespace NetworkResurrector.Api.Authorization.Constants
+{
+ public struct Policies
+ {
+ public const string
+ OperateMachines = "OPERATE_MACHINES";
+ }
+}
diff --git a/src/api/NetworkResurrector.Api/Authorization/DependencyInjectionExtensions.cs b/src/api/NetworkResurrector.Api/Authorization/DependencyInjectionExtensions.cs
new file mode 100644
index 0000000..55ca576
--- /dev/null
+++ b/src/api/NetworkResurrector.Api/Authorization/DependencyInjectionExtensions.cs
@@ -0,0 +1,24 @@
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.Extensions.DependencyInjection;
+using NetworkResurrector.Api.Authorization.Constants;
+using NetworkResurrector.Api.Authorization.Handlers;
+using NetworkResurrector.Api.Authorization.Requirements;
+
+namespace NetworkResurrector.Api.Authorization
+{
+ public static class DependencyInjectionExtensions
+ {
+ public static void AddLocalAuthorization(this IServiceCollection services)
+ {
+ services.AddAuthorization(options =>
+ {
+ options.AddPolicy(Policies.OperateMachines, policy =>
+ {
+ policy.Requirements.Add(new OperateMachinesRequirement());
+ });
+ });
+
+ services.AddScoped();
+ }
+ }
+}
diff --git a/src/api/NetworkResurrector.Api/Authorization/Handlers/OperateMachinesHandler.cs b/src/api/NetworkResurrector.Api/Authorization/Handlers/OperateMachinesHandler.cs
new file mode 100644
index 0000000..060c36f
--- /dev/null
+++ b/src/api/NetworkResurrector.Api/Authorization/Handlers/OperateMachinesHandler.cs
@@ -0,0 +1,27 @@
+using Microsoft.AspNetCore.Authorization;
+using NetworkResurrector.Api.Application.Services.Abstractions;
+using NetworkResurrector.Api.Authorization.Requirements;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace NetworkResurrector.Api.Authorization.Handlers
+{
+ public class OperateMachinesHandler : AuthorizationHandler
+ {
+ private readonly IUserContext _userContext;
+
+ public OperateMachinesHandler(IUserContext userContext)
+ {
+ _userContext=userContext;
+ }
+
+ protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, OperateMachinesRequirement requirement)
+ {
+ var permissions = await _userContext.GetUserPermissions();
+ if (permissions.Contains(requirement.PermissionCode))
+ {
+ context.Succeed(requirement);
+ }
+ }
+ }
+}
diff --git a/src/api/NetworkResurrector.Api/Authorization/Requirements/OperateMachinesRequirement.cs b/src/api/NetworkResurrector.Api/Authorization/Requirements/OperateMachinesRequirement.cs
new file mode 100644
index 0000000..8ccdf05
--- /dev/null
+++ b/src/api/NetworkResurrector.Api/Authorization/Requirements/OperateMachinesRequirement.cs
@@ -0,0 +1,10 @@
+using Microsoft.AspNetCore.Authorization;
+using NetworkResurrector.Api.Domain.Constants;
+
+namespace NetworkResurrector.Api.Authorization.Requirements
+{
+ public class OperateMachinesRequirement : IAuthorizationRequirement
+ {
+ public readonly string PermissionCode = PermissionCodes.OPERATE_MACHINES;
+ }
+}
diff --git a/src/api/NetworkResurrector.Api/Controllers/ResurrectorController.cs b/src/api/NetworkResurrector.Api/Controllers/ResurrectorController.cs
index 46fe152..e469c2d 100644
--- a/src/api/NetworkResurrector.Api/Controllers/ResurrectorController.cs
+++ b/src/api/NetworkResurrector.Api/Controllers/ResurrectorController.cs
@@ -1,6 +1,7 @@
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
+using NetworkResurrector.Api.Authorization.Constants;
using NetworkResurrector.Api.PublishedLanguage.Commands;
using System.Threading.Tasks;
@@ -26,6 +27,7 @@ namespace NetworkResurrector.Api.Controllers
}
[HttpPost("ping")]
+ [Authorize(Policy = Policies.OperateMachines)]
public async Task PingMachine([FromBody] PingMachine pingMachine)
{
var result = await _mediator.Send(pingMachine);
diff --git a/src/api/NetworkResurrector.Api/Extensions/StartupExtensions.cs b/src/api/NetworkResurrector.Api/Extensions/StartupExtensions.cs
index 3ce270f..85f7d1e 100644
--- a/src/api/NetworkResurrector.Api/Extensions/StartupExtensions.cs
+++ b/src/api/NetworkResurrector.Api/Extensions/StartupExtensions.cs
@@ -3,6 +3,7 @@ using MediatR.Pipeline;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
+using Netmash.Extensions.Caching;
using Netmash.Extensions.Swagger;
using Netmash.Extensions.Swagger.Constants;
using Netmash.Infrastructure.DatabaseMigration;
@@ -10,6 +11,7 @@ using Netmash.Infrastructure.DatabaseMigration.Constants;
using Netmash.Security.Authentication.Tuitio;
using NetworkResurrector.Agent.Wrapper;
using NetworkResurrector.Api.Application;
+using NetworkResurrector.Api.Authorization;
using NetworkResurrector.Api.Domain.Data;
using NetworkResurrector.Server.Wrapper;
using Newtonsoft.Json;
@@ -26,6 +28,12 @@ namespace NetworkResurrector.Api.Extensions
// Add basic authentication
services.AddTuitioAuthentication(configuration.GetSection("Tuitio")["BaseAddress"]);
+ // Add authorization
+ services.AddLocalAuthorization();
+
+ // Add cache service
+ services.AddCacheService();
+
// MediatR
services.AddMediatR(typeof(Application.Queries.GetMachines).Assembly);
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(RequestPreProcessorBehavior<,>));