diff --git a/Moonlight/App/Extensions/Attributes/RequirePermissionAttribute.cs b/Moonlight/App/Extensions/Attributes/RequirePermissionAttribute.cs new file mode 100644 index 0000000..e6d6db4 --- /dev/null +++ b/Moonlight/App/Extensions/Attributes/RequirePermissionAttribute.cs @@ -0,0 +1,20 @@ +using Moonlight.App.Models.Enums; + +namespace Moonlight.App.Extensions.Attributes; + +public class RequirePermissionAttribute : Attribute +{ + public int PermissionInteger = 0; + + public RequirePermissionAttribute(){} + + public RequirePermissionAttribute(int perms) + { + PermissionInteger = perms; + } + + public RequirePermissionAttribute(Permission permission) + { + PermissionInteger = (int)permission; + } +} \ No newline at end of file diff --git a/Moonlight/Moonlight.csproj b/Moonlight/Moonlight.csproj index 1c5fe55..400b3ec 100644 --- a/Moonlight/Moonlight.csproj +++ b/Moonlight/Moonlight.csproj @@ -19,10 +19,12 @@ + + diff --git a/Moonlight/Pages/_Host.cshtml b/Moonlight/Pages/_Host.cshtml index 3d90fdb..be86ec3 100644 --- a/Moonlight/Pages/_Host.cshtml +++ b/Moonlight/Pages/_Host.cshtml @@ -33,6 +33,7 @@ + \ No newline at end of file diff --git a/Moonlight/Program.cs b/Moonlight/Program.cs index 252122c..fb8fcce 100644 --- a/Moonlight/Program.cs +++ b/Moonlight/Program.cs @@ -1,3 +1,4 @@ +using BlazorTable; using Moonlight.App.Database; using Moonlight.App.Extensions; using Moonlight.App.Helpers; @@ -55,6 +56,7 @@ builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(); builder.Services.AddHttpContextAccessor(); builder.Services.AddControllers(); +builder.Services.AddBlazorTable(); builder.Logging.ClearProviders(); builder.Logging.AddProvider(new LogMigrateProvider()); diff --git a/Moonlight/Shared/Components/Navigations/AdminUsersNavigation.razor b/Moonlight/Shared/Components/Navigations/AdminUsersNavigation.razor new file mode 100644 index 0000000..956b307 --- /dev/null +++ b/Moonlight/Shared/Components/Navigations/AdminUsersNavigation.razor @@ -0,0 +1,22 @@ +
+ +
+ +@code +{ + [Parameter] + public int Index { get; set; } +} \ No newline at end of file diff --git a/Moonlight/Shared/Components/Partials/LazyLoader.razor b/Moonlight/Shared/Components/Partials/LazyLoader.razor new file mode 100644 index 0000000..7da0ced --- /dev/null +++ b/Moonlight/Shared/Components/Partials/LazyLoader.razor @@ -0,0 +1,50 @@ +@if (loaded) +{ + @ChildContent +} +else +{ +
+ + @(Text) +
+} + +@code +{ + [Parameter] + public RenderFragment ChildContent { get; set; } + + [Parameter] + public Func Load { get; set; } + + [Parameter] + public string Text { get; set; } = ""; + + private bool loaded = false; + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + await Load.Invoke(this); + loaded = true; + await InvokeAsync(StateHasChanged); + } + } + + public async Task SetText(string text) + { + Text = text; + await InvokeAsync(StateHasChanged); + } + + public async Task Reload() + { + loaded = false; + await InvokeAsync(StateHasChanged); + await Load.Invoke(this); + loaded = true; + await InvokeAsync(StateHasChanged); + } +} \ No newline at end of file diff --git a/Moonlight/Shared/Components/Partials/PermissionChecker.razor b/Moonlight/Shared/Components/Partials/PermissionChecker.razor new file mode 100644 index 0000000..227be23 --- /dev/null +++ b/Moonlight/Shared/Components/Partials/PermissionChecker.razor @@ -0,0 +1,64 @@ +@using Moonlight.App.Extensions.Attributes +@using Moonlight.App.Models.Abstractions +@using Moonlight.App.Services + +@inject IdentityService IdentityService + +@if (Allowed) +{ + @ChildContent +} +else +{ +

Ha, nein ;)

+} + +@code +{ + [CascadingParameter(Name = "TargetPageType")] + public Type? TargetPageType { get; set; } + + [Parameter] + public RenderFragment ChildContent { get; set; } + + private bool Allowed = false; + + protected override Task OnParametersSetAsync() + { + if(TargetPageType == null) + return Task.CompletedTask; + + var attributes = TargetPageType.GetCustomAttributes(true); + var permAttrs = attributes + .Where(x => x.GetType() == typeof(RequirePermissionAttribute)) + .Select(x => x as RequirePermissionAttribute) + .ToArray(); + + Allowed = true; + + if (permAttrs.Any()) + { + Allowed = false; + + foreach (var permissionRequired in permAttrs) + { + if(permissionRequired == null) + continue; + + var permission = PermissionStorage.GetFromInteger(permissionRequired.PermissionInteger); + + if (IdentityService.Permissions[permission]) + { + Allowed = true; + } + } + } + + if (!Allowed) + { + //Logger.Warn($"{IdentityService.Ip} has tried to access {NavigationManager.Uri} without permission", "security"); + } + + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/Moonlight/Shared/Components/Partials/Sidebar.razor b/Moonlight/Shared/Components/Partials/Sidebar.razor index d625e5b..8d02ef2 100644 --- a/Moonlight/Shared/Components/Partials/Sidebar.razor +++ b/Moonlight/Shared/Components/Partials/Sidebar.razor @@ -1,4 +1,8 @@ @using Moonlight.Shared.Layouts +@using Moonlight.App.Services +@using Moonlight.App.Models.Enums + +@inject IdentityService IdentityService
@@ -20,6 +24,67 @@
+ + + + @if (IdentityService.Permissions[Permission.AdminMenu]) + { + + + + + + }
diff --git a/Moonlight/Shared/Components/Partials/SoftErrorHandler.razor b/Moonlight/Shared/Components/Partials/SoftErrorHandler.razor index 7e7934d..61db135 100644 --- a/Moonlight/Shared/Components/Partials/SoftErrorHandler.razor +++ b/Moonlight/Shared/Components/Partials/SoftErrorHandler.razor @@ -1,11 +1,14 @@ @using System.Diagnostics @using Moonlight.App.Exceptions +@using Moonlight.App.Models.Enums +@using Moonlight.App.Services @inherits ErrorBoundaryBase +@inject IdentityService IdentityService @if (Crashed) { - if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development") // TODO: Add check for admin perms to show exceptions to admins + if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development" || IdentityService.Permissions[Permission.AdminViewExceptions]) // TODO: Add check for admin perms to show exceptions to admins { if (Exception != null) { diff --git a/Moonlight/Shared/Layouts/MainLayout.razor b/Moonlight/Shared/Layouts/MainLayout.razor index 90b6507..d1e5097 100644 --- a/Moonlight/Shared/Layouts/MainLayout.razor +++ b/Moonlight/Shared/Layouts/MainLayout.razor @@ -36,7 +36,9 @@ { - @Body + + @Body + } diff --git a/Moonlight/Shared/Views/Admin/Index.razor b/Moonlight/Shared/Views/Admin/Index.razor new file mode 100644 index 0000000..a91ce60 --- /dev/null +++ b/Moonlight/Shared/Views/Admin/Index.razor @@ -0,0 +1,6 @@ +@page "/admin" + +@using Moonlight.App.Extensions.Attributes +@using Moonlight.App.Models.Enums + +@attribute [RequirePermission(Permission.AdminOverview)] \ No newline at end of file diff --git a/Moonlight/Shared/Views/Admin/Users/Index.razor b/Moonlight/Shared/Views/Admin/Users/Index.razor new file mode 100644 index 0000000..5b8ea12 --- /dev/null +++ b/Moonlight/Shared/Views/Admin/Users/Index.razor @@ -0,0 +1,52 @@ +@page "/admin/users" + +@using Moonlight.App.Extensions.Attributes +@using Moonlight.App.Models.Enums +@using Moonlight.App.Repositories +@using BlazorTable + +@attribute [RequirePermission(Permission.AdminUsers)] + +@inject Repository UserRepository + + + +
+
+ + + + + + + + + + + +
+
+
+
+ +@code +{ + private User[] AllUsers; + + private Task Load(LazyLoader _) + { + AllUsers = UserRepository + .Get() + .ToArray(); + + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/Moonlight/Shared/Views/Admin/Users/Sessions.razor b/Moonlight/Shared/Views/Admin/Users/Sessions.razor new file mode 100644 index 0000000..adfc0bd --- /dev/null +++ b/Moonlight/Shared/Views/Admin/Users/Sessions.razor @@ -0,0 +1,61 @@ +@page "/admin/users/sessions" + +@using Moonlight.App.Extensions.Attributes +@using Moonlight.App.Models.Enums +@using BlazorTable +@using Moonlight.App.Models.Abstractions +@using Moonlight.App.Services + +@attribute [RequirePermission(Permission.AdminSessions)] + +@inject SessionService SessionService + + + +
+
+ + + + + + + + + + + + + + +
+
+
+
+ +@code +{ + private Task Load(LazyLoader _) + { + Task.Run(async () => + { + while (true) + { + await InvokeAsync(StateHasChanged); + await Task.Delay(TimeSpan.FromSeconds(1)); + } + }); + + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/Moonlight/Shared/Views/Index.razor b/Moonlight/Shared/Views/Index.razor index be73be9..11f04b9 100644 --- a/Moonlight/Shared/Views/Index.razor +++ b/Moonlight/Shared/Views/Index.razor @@ -1,20 +1,38 @@ @page "/" -@using Moonlight.App.Exceptions -

Hello, world!

+@using Moonlight.App.Services - - +@inject IdentityService IdentityService -@code -{ - private async Task Do() - { - throw new DisplayException("LOL"); - } - - private async Task Do2() - { - throw new FormatException("LOL"); - } -} +
+
+ Welcome back, @(IdentityService.CurrentUser.Username) +
+
+ +
+
+
+
+ Do you want to order new services? Are you searching for our service specifications and prices? +
+ Go to store +
+
+
+
+
+ Do you want to order new services? Are you searching for our service specifications and prices? +
+ Go to store +
+
+
+
+
+ Do you want to order new services? Are you searching for our service specifications and prices? +
+ Go to store +
+
+
\ No newline at end of file diff --git a/Moonlight/_Imports.razor b/Moonlight/_Imports.razor index e0a8768..dba000c 100644 --- a/Moonlight/_Imports.razor +++ b/Moonlight/_Imports.razor @@ -7,4 +7,5 @@ @using Moonlight.Shared.Components.Forms @using Moonlight.Shared.Components.Navigations @using Moonlight.App.Services.Interop -@using Moonlight.App.Exceptions \ No newline at end of file +@using Moonlight.App.Exceptions +@using Moonlight.App.Database.Entities \ No newline at end of file diff --git a/Moonlight/wwwroot/img/covers/minecraft.png b/Moonlight/wwwroot/img/covers/minecraft.png new file mode 100644 index 0000000..877f204 Binary files /dev/null and b/Moonlight/wwwroot/img/covers/minecraft.png differ