initial permissions based webfront access implementation

This commit is contained in:
RaidMax 2022-04-04 22:16:40 -05:00
parent dc97956bc3
commit 19bd47d0f4
8 changed files with 125 additions and 41 deletions

View File

@ -30,6 +30,7 @@ namespace SharedLibraryCore
private static string SocialTitle; private static string SocialTitle;
protected readonly DatabaseContext Context; protected readonly DatabaseContext Context;
protected List<Page> Pages; protected List<Page> Pages;
protected List<string> PermissionsSet;
public BaseController(IManager manager) public BaseController(IManager manager)
{ {
@ -43,7 +44,6 @@ namespace SharedLibraryCore
SocialTitle = AppConfig.SocialLinkTitle; SocialTitle = AppConfig.SocialLinkTitle;
} }
Pages = Manager.GetPageList().Pages Pages = Manager.GetPageList().Pages
.Select(page => new Page .Select(page => new Page
{ {
@ -135,6 +135,11 @@ namespace SharedLibraryCore
var claimsIdentity = new ClaimsIdentity(claims, "login"); var claimsIdentity = new ClaimsIdentity(claims, "login");
SignInAsync(new ClaimsPrincipal(claimsIdentity)).Wait(); SignInAsync(new ClaimsPrincipal(claimsIdentity)).Wait();
} }
if (AppConfig.PermissionSets.ContainsKey(Client.Level.ToString()))
{
PermissionsSet = AppConfig.PermissionSets[Client.Level.ToString()];
}
var communityName = AppConfig.CommunityInformation?.Name; var communityName = AppConfig.CommunityInformation?.Name;
var shouldUseCommunityName = !string.IsNullOrWhiteSpace(communityName) var shouldUseCommunityName = !string.IsNullOrWhiteSpace(communityName)
@ -160,4 +165,4 @@ namespace SharedLibraryCore
base.OnActionExecuting(context); base.OnActionExecuting(context);
} }
} }
} }

View File

@ -115,7 +115,7 @@ namespace SharedLibraryCore.Configuration
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_ENABLE_COLOR_CODES")] [LocalizedDisplayName("WEBFRONT_CONFIGURATION_ENABLE_COLOR_CODES")]
public bool EnableColorCodes { get; set; } public bool EnableColorCodes { get; set; }
[ConfigurationIgnore] public string IngameAccentColorKey { get; set; } = "Cyan"; [ConfigurationIgnore] public string IngameAccentColorKey { get; set; } = "Cyan";
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_AUTOMESSAGE_PERIOD")] [LocalizedDisplayName("WEBFRONT_CONFIGURATION_AUTOMESSAGE_PERIOD")]
@ -144,6 +144,16 @@ namespace SharedLibraryCore.Configuration
TimeSpan.FromDays(30) TimeSpan.FromDays(30)
}; };
public Dictionary<string, List<string>> PermissionSets { get; set; } = new()
{
{ Permission.Trusted.ToString(), new List<string> { "*" } },
{ Permission.Moderator.ToString(), new List<string> { "*" } },
{ Permission.Administrator.ToString(), new List<string> { "*" } },
{ Permission.SeniorAdmin.ToString(), new List<string> { "*" } },
{ Permission.Owner.ToString(), new List<string> { "*" } },
{ Permission.Console.ToString(), new List<string> { "*" } }
};
[ConfigurationIgnore] [ConfigurationIgnore]
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_PRESET_BAN_REASONS")] [LocalizedDisplayName("WEBFRONT_CONFIGURATION_PRESET_BAN_REASONS")]
public Dictionary<string, string> PresetPenaltyReasons { get; set; } = new Dictionary<string, string> public Dictionary<string, string> PresetPenaltyReasons { get; set; } = new Dictionary<string, string>

View File

@ -525,6 +525,45 @@ namespace SharedLibraryCore
return new TimeSpan(1, 0, 0); return new TimeSpan(1, 0, 0);
} }
public static bool HasPermission<TEntity, TPermission>(this IEnumerable<string> permissionsSet, TEntity entity,
TPermission permission) where TEntity : Enum where TPermission : Enum
{
return permissionsSet?.Any(raw =>
{
if (raw == "*")
{
return true;
}
var split = raw.Split(".");
if (split.Length != 2)
{
return false;
}
if (!Enum.TryParse(typeof(TEntity), split[0], out var e))
{
return false;
}
if (!Enum.TryParse(typeof(TPermission), split[1], out var p))
{
return false;
}
return (e?.Equals(entity) ?? false) && (p?.Equals(permission) ?? false);
}) ?? false;
}
public static bool HasPermission<TEntity, TPermission>(this ApplicationConfiguration appConfig,
Permission permissionLevel, TEntity entity,
TPermission permission) where TEntity : Enum where TPermission : Enum
{
return appConfig.PermissionSets.ContainsKey(permissionLevel.ToString()) &&
HasPermission(appConfig.PermissionSets[permissionLevel.ToString()], entity, permission);
}
/// <summary> /// <summary>
/// returns a list of penalty types that should be shown across all profiles /// returns a list of penalty types that should be shown across all profiles
/// </summary> /// </summary>

View File

@ -10,6 +10,7 @@ using SharedLibraryCore;
using SharedLibraryCore.Commands; using SharedLibraryCore.Commands;
using SharedLibraryCore.Configuration; using SharedLibraryCore.Configuration;
using SharedLibraryCore.Interfaces; using SharedLibraryCore.Interfaces;
using WebfrontCore.Permissions;
using WebfrontCore.ViewModels; using WebfrontCore.ViewModels;
namespace WebfrontCore.Controllers namespace WebfrontCore.Controllers
@ -314,6 +315,14 @@ namespace WebfrontCore.Controllers
public async Task<IActionResult> RecentClientsForm() public async Task<IActionResult> RecentClientsForm()
{ {
var clients = await Manager.GetClientService().GetRecentClients(); var clients = await Manager.GetClientService().GetRecentClients();
foreach (var client in clients)
{
client.IPAddress =
_appConfig.HasPermission(Client.Level, WebfrontEntity.IPAddress, WebfrontPermission.Read)
? client.IPAddress
: null;
}
return View("~/Views/Shared/Components/Client/_RecentClients.cshtml", clients); return View("~/Views/Shared/Components/Client/_RecentClients.cshtml", clients);
} }
@ -453,4 +462,4 @@ namespace WebfrontCore.Controllers
}) })
.ToDictionary(item => item.Value, item => item.Value); .ToDictionary(item => item.Value, item => item.Value);
} }
} }

View File

@ -7,11 +7,13 @@ using SharedLibraryCore.Interfaces;
using SharedLibraryCore.QueryHelper; using SharedLibraryCore.QueryHelper;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Data.Models; using Data.Models;
using Stats.Config; using Stats.Config;
using WebfrontCore.Permissions;
using WebfrontCore.ViewComponents; using WebfrontCore.ViewComponents;
namespace WebfrontCore.Controllers namespace WebfrontCore.Controllers
@ -79,7 +81,7 @@ namespace WebfrontCore.Controllers
Level = displayLevel, Level = displayLevel,
LevelInt = displayLevelInt, LevelInt = displayLevelInt,
ClientId = client.ClientId, ClientId = client.ClientId,
IPAddress = client.IPAddressString, IPAddress = PermissionsSet.HasPermission(WebfrontEntity.IPAddress, WebfrontPermission.Read) ? client.IPAddressString : null,
NetworkId = client.NetworkId, NetworkId = client.NetworkId,
Meta = new List<InformationResponse>(), Meta = new List<InformationResponse>(),
Aliases = client.AliasLink.Children Aliases = client.AliasLink.Children
@ -90,13 +92,13 @@ namespace WebfrontCore.Controllers
.Distinct() .Distinct()
.OrderBy(a => a) .OrderBy(a => a)
.ToList(), .ToList(),
IPs = client.AliasLink.Children IPs = PermissionsSet.HasPermission(WebfrontEntity.IPAddress, WebfrontPermission.Read) ? client.AliasLink.Children
.Where(i => i.IPAddress != null) .Where(i => i.IPAddress != null)
.OrderByDescending(i => i.DateAdded) .OrderByDescending(i => i.DateAdded)
.Select(i => i.IPAddress.ConvertIPtoString()) .Select(i => i.IPAddress.ConvertIPtoString())
.Prepend(client.CurrentAlias.IPAddress.ConvertIPtoString()) .Prepend(client.CurrentAlias.IPAddress.ConvertIPtoString())
.Distinct() .Distinct()
.ToList(), .ToList() : new List<string>(),
HasActivePenalty = activePenalties.Any(_penalty => _penalty.Type != EFPenalty.PenaltyType.Flag), HasActivePenalty = activePenalties.Any(_penalty => _penalty.Type != EFPenalty.PenaltyType.Flag),
Online = Manager.GetActiveClients().FirstOrDefault(c => c.ClientId == client.ClientId) != null, Online = Manager.GetActiveClients().FirstOrDefault(c => c.ClientId == client.ClientId) != null,
TimeOnline = (DateTime.UtcNow - client.LastConnection).HumanizeForCurrentCulture(), TimeOnline = (DateTime.UtcNow - client.LastConnection).HumanizeForCurrentCulture(),
@ -191,7 +193,7 @@ namespace WebfrontCore.Controllers
return View("Find/Index", clientsDto); return View("Find/Index", clientsDto);
} }
public async Task<IActionResult> Meta(int id, int count, int offset, long? startAt, MetaType? metaFilterType, CancellationToken token) public IActionResult Meta(int id, int count, int offset, long? startAt, MetaType? metaFilterType, CancellationToken token)
{ {
var request = new ClientPaginationRequest var request = new ClientPaginationRequest
{ {
@ -201,14 +203,15 @@ namespace WebfrontCore.Controllers
Before = DateTime.FromFileTimeUtc(startAt ?? DateTime.UtcNow.ToFileTimeUtc()) Before = DateTime.FromFileTimeUtc(startAt ?? DateTime.UtcNow.ToFileTimeUtc())
}; };
var meta = await ProfileMetaListViewComponent.GetClientMeta(_metaService, metaFilterType, Client.Level, request, token); return ViewComponent(typeof(ProfileMetaListViewComponent), new
if (!meta.Any())
{ {
return Ok(); clientId = request.ClientId,
} count = request.Count,
offset = request.Offset,
return View("Components/ProfileMetaList/_List", meta); startAt = request.Before,
metaType = metaFilterType,
token
});
} }
} }
} }

View File

@ -0,0 +1,15 @@
namespace WebfrontCore.Permissions;
public enum WebfrontEntity
{
IPAddress,
MetaAliasUpdate
}
public enum WebfrontPermission
{
Read,
Create,
Update,
Delete
}

View File

@ -9,16 +9,21 @@ using System.Linq;
using System.Security.Claims; using System.Security.Claims;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using SharedLibraryCore;
using SharedLibraryCore.Configuration;
using WebfrontCore.Permissions;
namespace WebfrontCore.ViewComponents namespace WebfrontCore.ViewComponents
{ {
public class ProfileMetaListViewComponent : ViewComponent public class ProfileMetaListViewComponent : ViewComponent
{ {
private readonly IMetaServiceV2 _metaService; private readonly IMetaServiceV2 _metaService;
private readonly ApplicationConfiguration _appConfig;
public ProfileMetaListViewComponent(IMetaServiceV2 metaService) public ProfileMetaListViewComponent(IMetaServiceV2 metaService, ApplicationConfiguration appConfig)
{ {
_metaService = metaService; _metaService = metaService;
_appConfig = appConfig;
} }
public async Task<IViewComponentResult> InvokeAsync(int clientId, int count, int offset, DateTime? startAt, MetaType? metaType, CancellationToken token) public async Task<IViewComponentResult> InvokeAsync(int clientId, int count, int offset, DateTime? startAt, MetaType? metaType, CancellationToken token)
@ -39,11 +44,16 @@ namespace WebfrontCore.ViewComponents
return View("_List", meta); return View("_List", meta);
} }
public static async Task<IEnumerable<IClientMeta>> GetClientMeta(IMetaServiceV2 metaService, MetaType? metaType, private async Task<IEnumerable<IClientMeta>> GetClientMeta(IMetaServiceV2 metaService, MetaType? metaType,
EFClient.Permission level, ClientPaginationRequest request, CancellationToken token) EFClient.Permission level, ClientPaginationRequest request, CancellationToken token)
{ {
IEnumerable<IClientMeta> meta = null; IEnumerable<IClientMeta> meta = null;
if (!_appConfig.PermissionSets.TryGetValue(level.ToString(), out var permissionSet))
{
permissionSet = new List<string>();
}
if (metaType is null or MetaType.All) if (metaType is null or MetaType.All)
{ {
meta = await metaService.GetRuntimeMeta(request, token); meta = await metaService.GetRuntimeMeta(request, token);
@ -51,30 +61,24 @@ namespace WebfrontCore.ViewComponents
else else
{ {
switch (metaType) meta = metaType switch
{ {
case MetaType.Information: MetaType.Information => await metaService.GetRuntimeMeta<InformationResponse>(request,
meta = await metaService.GetRuntimeMeta<InformationResponse>(request, metaType.Value, token); metaType.Value, token),
break; MetaType.AliasUpdate => permissionSet.HasPermission(WebfrontEntity.MetaAliasUpdate, WebfrontPermission.Read) ? await metaService.GetRuntimeMeta<UpdatedAliasResponse>(request,
case MetaType.AliasUpdate: metaType.Value, token) : new List<IClientMeta>(),
meta = await metaService.GetRuntimeMeta<UpdatedAliasResponse>(request, metaType.Value, token); MetaType.ChatMessage => await metaService.GetRuntimeMeta<MessageResponse>(request, metaType.Value,
break; token),
case MetaType.ChatMessage: MetaType.Penalized => await metaService.GetRuntimeMeta<AdministeredPenaltyResponse>(request,
meta = await metaService.GetRuntimeMeta<MessageResponse>(request, metaType.Value, token); metaType.Value, token),
break; MetaType.ReceivedPenalty => await metaService.GetRuntimeMeta<ReceivedPenaltyResponse>(request,
case MetaType.Penalized: metaType.Value, token),
meta = await metaService.GetRuntimeMeta<AdministeredPenaltyResponse>(request, metaType.Value, token); MetaType.ConnectionHistory => await metaService.GetRuntimeMeta<ConnectionHistoryResponse>(request,
break; metaType.Value, token),
case MetaType.ReceivedPenalty: MetaType.PermissionLevel => await metaService.GetRuntimeMeta<PermissionLevelChangedResponse>(
meta = await metaService.GetRuntimeMeta<ReceivedPenaltyResponse>(request, metaType.Value, token); request, metaType.Value, token),
break; _ => meta
case MetaType.ConnectionHistory: };
meta = await metaService.GetRuntimeMeta<ConnectionHistoryResponse>(request, metaType.Value, token);
break;
case MetaType.PermissionLevel:
meta = await metaService.GetRuntimeMeta<PermissionLevelChangedResponse>(request, metaType.Value, token);
break;
}
} }
if (level < EFClient.Permission.Trusted) if (level < EFClient.Permission.Trusted)

View File

@ -1,5 +1,4 @@
@using SharedLibraryCore.Dtos.Meta.Responses @using SharedLibraryCore.Dtos.Meta.Responses
@using SharedLibraryCore
@model UpdatedAliasResponse @model UpdatedAliasResponse
@foreach (var token in Utilities.SplitTranslationTokens("WEBFRONT_PROFILE_META_CONNECT_ALIAS")) @foreach (var token in Utilities.SplitTranslationTokens("WEBFRONT_PROFILE_META_CONNECT_ALIAS"))