Switched to new mooncore authentication service

This commit is contained in:
Marcel Baumgartner
2024-07-06 11:29:45 +02:00
parent e53a1bad0e
commit dcef6e4500
30 changed files with 224 additions and 261 deletions

View File

@@ -90,6 +90,16 @@ public class CoreConfiguration
[JsonProperty("DenyRegister")] [JsonProperty("DenyRegister")]
[Description("This disables the register function. No user will be able to sign up anymore. Its recommended to enable this for private instances")] [Description("This disables the register function. No user will be able to sign up anymore. Its recommended to enable this for private instances")]
public bool DenyRegister { get; set; } = false; public bool DenyRegister { get; set; } = false;
[JsonProperty("EnablePeriodicReAuth")]
[Description(
"If this option is enabled, every session will reauthenticate perdiodicly to track state changes in real time without the user refreshing the page")]
public bool EnablePeriodicReAuth { get; set; } = true;
[JsonProperty("PeriodicReAuthDelay")]
[Description(
"This option specifies how long the intervals are between reauthentications. The value is specified in minutes")]
public int PeriodicReAuthDelay { get; set; } = 5;
} }
public class SecurityData public class SecurityData

View File

@@ -26,7 +26,7 @@ using Moonlight.Core.Implementations.AdminDashboard;
using Moonlight.Core.Implementations.ApiDefinition; using Moonlight.Core.Implementations.ApiDefinition;
using Moonlight.Core.Implementations.UserDashboard; using Moonlight.Core.Implementations.UserDashboard;
using Swashbuckle.AspNetCore.SwaggerGen; using Swashbuckle.AspNetCore.SwaggerGen;
using IdentityService = Moonlight.Core.Services.IdentityService; using AuthenticationStateProvider = Moonlight.Core.Helpers.AuthenticationStateProvider;
namespace Moonlight.Core; namespace Moonlight.Core;
@@ -68,6 +68,9 @@ public class CoreFeature : MoonlightFeature
builder.Services.AddMoonCore(configuration => builder.Services.AddMoonCore(configuration =>
{ {
configuration.Identity.Token = config.Security.Token; configuration.Identity.Token = config.Security.Token;
configuration.Identity.PeriodicReAuthDelay = TimeSpan.FromMinutes(config.Authentication.PeriodicReAuthDelay);
configuration.Identity.EnablePeriodicReAuth = config.Authentication.EnablePeriodicReAuth;
configuration.Identity.Provider = new AuthenticationStateProvider();
}); });
builder.Services.AddMoonCoreBlazor(); builder.Services.AddMoonCoreBlazor();

View File

@@ -0,0 +1,54 @@
using MoonCore.Abstractions;
using MoonCore.Services;
using Moonlight.Core.Database.Entities;
namespace Moonlight.Core.Extensions;
public static class IdentityServiceExtensions
{
public static User GetUser(this IdentityService identityService)
{
return identityService.Storage.Get<User>();
}
public static Task<bool> HasFlag(this IdentityService identityService, string flag)
{
if (!identityService.IsAuthenticated)
return Task.FromResult(false);
var result = identityService.GetUser().Flags.Split(";").Contains(flag);
return Task.FromResult(result);
}
public static Task SetFlag(this IdentityService identityService, string flag, bool toggle)
{
if (!identityService.IsAuthenticated)
return Task.CompletedTask;
var user = identityService.GetUser();
// Rebuild flags
var flags = user.Flags.Split(";").ToList();
if (toggle)
{
if(!flags.Contains(flag))
flags.Add(flag);
}
else
{
if (flags.Contains(flag))
flags.Remove(flag);
}
user.Flags = string.Join(';', flags);
// Save changes
var serviceProvider = identityService.Storage.Get<IServiceProvider>();
var userRepo = serviceProvider.GetRequiredService<Repository<User>>();
userRepo.Update(user);
return Task.CompletedTask;
}
}

View File

@@ -0,0 +1,50 @@
using MoonCore.Abstractions;
using MoonCore.Helpers;
using Moonlight.Core.Database.Entities;
namespace Moonlight.Core.Helpers;
public class AuthenticationStateProvider : MoonCore.Abstractions.AuthenticationStateProvider
{
public override Task<bool> IsValidIdentifier(IServiceProvider provider, string identifier)
{
if(!int.TryParse(identifier, out int searchId))
return Task.FromResult(false);
var userRepo = provider.GetRequiredService<Repository<User>>();
var result = userRepo.Get().Any(x => x.Id == searchId);
return Task.FromResult(result);
}
public override Task LoadFromIdentifier(IServiceProvider provider, string identifier, DynamicStorage storage)
{
if(!int.TryParse(identifier, out int searchId))
return Task.CompletedTask;
var userRepo = provider.GetRequiredService<Repository<User>>();
var user = userRepo.Get().FirstOrDefault(x => x.Id == searchId);
if(user == null)
return Task.CompletedTask;
storage.Set("User", user);
storage.Set("ServiceProvider", provider);
return Task.CompletedTask;
}
public override Task<DateTime> DetermineTokenValidTimestamp(IServiceProvider provider, string identifier)
{
if(!int.TryParse(identifier, out int searchId))
return Task.FromResult(DateTime.MaxValue);
var userRepo = provider.GetRequiredService<Repository<User>>();
var user = userRepo.Get().FirstOrDefault(x => x.Id == searchId);
if(user == null)
return Task.FromResult(DateTime.MaxValue);
return Task.FromResult(user.TokenValidTimestamp);
}
}

View File

@@ -2,13 +2,11 @@
using System.Text; using System.Text;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using MoonCore.Abstractions; using MoonCore.Abstractions;
using MoonCore.Helpers;
using MoonCore.Services; using MoonCore.Services;
using Moonlight.Core.Attributes; using Moonlight.Core.Attributes;
using Moonlight.Core.Configuration; using Moonlight.Core.Configuration;
using Moonlight.Core.Database.Entities; using Moonlight.Core.Database.Entities;
using Moonlight.Core.Services; using Moonlight.Core.Extensions;
using IdentityService = Moonlight.Core.Services.IdentityService;
namespace Moonlight.Core.Http.Controllers; namespace Moonlight.Core.Http.Controllers;
@@ -42,10 +40,10 @@ public class AvatarController : Controller
var token = Request.Cookies["token"]; var token = Request.Cookies["token"];
await IdentityService.Authenticate(token!); await IdentityService.Authenticate(token!);
if (!IdentityService.IsLoggedIn) if (!IdentityService.IsAuthenticated)
return StatusCode(403); return StatusCode(403);
return File(await GetAvatar(IdentityService.CurrentUser), "image/jpeg"); return File(await GetAvatar(IdentityService.GetUser()), "image/jpeg");
} }
[HttpGet("{id:int}")] [HttpGet("{id:int}")]
@@ -57,12 +55,12 @@ public class AvatarController : Controller
var token = Request.Cookies["token"]; var token = Request.Cookies["token"];
await IdentityService.Authenticate(token!); await IdentityService.Authenticate(token!);
if (!IdentityService.IsLoggedIn) if (!IdentityService.IsAuthenticated)
return StatusCode(403); return StatusCode(403);
if (ConfigService.Get().Security.EnforceAvatarPrivacy && // Do we need to enforce privacy? if (ConfigService.Get().Security.EnforceAvatarPrivacy && // Do we need to enforce privacy?
id != IdentityService.CurrentUser.Id && // is the user not viewing his own image? id != IdentityService.GetUser().Id && // is the user not viewing his own image?
IdentityService.CurrentUser.Permissions < 1000) // and not an admin? IdentityService.GetUser().Permissions < 1000) // and not an admin?
{ {
return StatusCode(403); return StatusCode(403);
} }

View File

@@ -4,12 +4,6 @@ namespace Moonlight.Core.Models.Forms;
public class UpdateAccountForm public class UpdateAccountForm
{ {
[Required(ErrorMessage = "You need to provide an username")]
[MinLength(6, ErrorMessage = "The username is too short")]
[MaxLength(20, ErrorMessage = "The username cannot be longer than 20 characters")]
public string Username { get; set; } public string Username { get; set; }
[Required(ErrorMessage = "You need to provide an email address")]
[EmailAddress(ErrorMessage = "You need to enter a valid email address")]
public string Email { get; set; } = ""; public string Email { get; set; } = "";
} }

View File

@@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using MoonCore.Blazor.Services; using MoonCore.Blazor.Services;
using Moonlight.Core.Services; using MoonCore.Services;
namespace Moonlight.Core.Models; namespace Moonlight.Core.Models;

View File

@@ -1,147 +0,0 @@
using MoonCore.Abstractions;
using MoonCore.Attributes;
using MoonCore.Exceptions;
using MoonCore.Helpers;
using MoonCore.Services;
using Moonlight.Core.Configuration;
using Moonlight.Core.Database.Entities;
using Moonlight.Core.Models.Enums;
namespace Moonlight.Core.Services;
[Scoped]
public class IdentityService : IDisposable
{
public User? CurrentUserNullable { get; private set; }
public User CurrentUser => CurrentUserNullable!;
public bool IsLoggedIn => CurrentUserNullable != null;
public SmartEventHandler OnAuthenticationStateChanged { get; set; }
private string Token = "";
private readonly JwtService<CoreJwtType> JwtService;
private readonly ConfigService<CoreConfiguration> ConfigService;
private readonly Repository<User> UserRepository;
public IdentityService(
JwtService<CoreJwtType> jwtService,
ConfigService<CoreConfiguration> configService,
Repository<User> userRepository,
ILogger<SmartEventHandler> eventHandlerLogger)
{
JwtService = jwtService;
ConfigService = configService;
UserRepository = userRepository;
OnAuthenticationStateChanged = new(eventHandlerLogger);
}
public async Task<string> Authenticate(User user)
{
var duration = TimeSpan.FromDays(ConfigService.Get().Authentication.TokenDuration);
var token = await JwtService.Create(data =>
{
data.Add("UserId", user.Id.ToString());
data.Add("IssuedAt", DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString());
}, CoreJwtType.Login, duration);
await Authenticate(token);
return token;
}
public async Task Authenticate(string token)
{
Token = token;
await Authenticate();
}
public async Task Authenticate(bool forceStateChange = false) // Can be used for authentication of the token as well
{
var lastUserId = CurrentUserNullable?.Id ?? -1;
await ProcessToken();
var currentUserId = CurrentUserNullable?.Id ?? -1;
if (lastUserId != currentUserId || forceStateChange)
await OnAuthenticationStateChanged.Invoke();
}
private async Task ProcessToken()
{
CurrentUserNullable = null;
// Check jwt signature
if (!await JwtService.Validate(Token, CoreJwtType.Login))
return;
var data = await JwtService.Decode(Token);
// Check for missing content
if(!data.ContainsKey("UserId") || !data.ContainsKey("IssuedAt"))
return;
// Load user
var userId = int.Parse(data["UserId"]);
var user = UserRepository
.Get()
.FirstOrDefault(x => x.Id == userId);
// Check if user was found
if(user == null)
return;
// Check token valid time
var issuedAt = long.Parse(data["IssuedAt"]);
var issuedAtDateTime = DateTimeOffset.FromUnixTimeSeconds(issuedAt).DateTime;
// If the valid time is newer then when the token was issued, the token is not longer valid
if (user.TokenValidTimestamp > issuedAtDateTime)
return;
CurrentUserNullable = user;
}
public Task<bool> HasFlag(string flag)
{
if (!IsLoggedIn)
return Task.FromResult(false);
var flags = CurrentUser.Flags.Split(";");
return Task.FromResult(flags.Contains(flag));
}
public Task SetFlag(string flag, bool toggle)
{
if (!IsLoggedIn)
throw new DisplayException("Unable to set flag while not logged in");
var flags = CurrentUser.Flags.Split(";").ToList();
if (toggle)
{
if(!flags.Contains(flag))
flags.Add(flag);
}
else
{
if (flags.Contains(flag))
flags.Remove(flag);
}
CurrentUser.Flags = string.Join(';', flags);
UserRepository.Update(CurrentUser);
return Task.CompletedTask;
}
public async void Dispose()
{
await OnAuthenticationStateChanged.ClearSubscribers();
}
}

View File

@@ -3,13 +3,14 @@
@using Moonlight.Core.Models.Abstractions @using Moonlight.Core.Models.Abstractions
@using Moonlight.Core.Models.Forms @using Moonlight.Core.Models.Forms
@using Moonlight.Core.Services
@using MoonCore.Exceptions @using MoonCore.Exceptions
@using Moonlight.Core.Configuration
@inject IAuthenticationProvider AuthenticationProvider @inject IAuthenticationProvider AuthenticationProvider
@inject IdentityService IdentityService @inject IdentityService IdentityService
@inject CookieService CookieService @inject CookieService CookieService
@inject NavigationManager Navigation @inject NavigationManager Navigation
@inject ConfigService<CoreConfiguration> ConfigService
<div class="d-flex justify-content-center"> <div class="d-flex justify-content-center">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
@@ -89,7 +90,10 @@
throw new DisplayException("A user with these credential combination was not found"); throw new DisplayException("A user with these credential combination was not found");
// Generate token and authenticate // Generate token and authenticate
var token = await IdentityService.Authenticate(user); var token = await IdentityService.Login(
user.Id.ToString(),
TimeSpan.FromHours(ConfigService.Get().Authentication.TokenDuration)
);
// Save token for later use // Save token for later use
await CookieService.SetValue("token", token, 30); //TODO: Add days to config option await CookieService.SetValue("token", token, 30); //TODO: Add days to config option

View File

@@ -4,11 +4,8 @@
@using Moonlight.Core.Models.Abstractions @using Moonlight.Core.Models.Abstractions
@using Moonlight.Core.Models.Forms @using Moonlight.Core.Models.Forms
@using Moonlight.Core.Services
@using MoonCore.Exceptions @using MoonCore.Exceptions
@using MoonCore.Services
@using Moonlight.Core.Configuration @using Moonlight.Core.Configuration
@using IdentityService = Moonlight.Core.Services.IdentityService
@inject IAuthenticationProvider AuthenticationProvider @inject IAuthenticationProvider AuthenticationProvider
@inject IdentityService IdentityService @inject IdentityService IdentityService
@@ -96,7 +93,10 @@
throw new DisplayException("Unable to create account"); throw new DisplayException("Unable to create account");
// Generate token and authenticate // Generate token and authenticate
var token = await IdentityService.Authenticate(user); var token = await IdentityService.Login(
user.Id.ToString(),
TimeSpan.FromHours(ConfigService.Get().Authentication.TokenDuration)
);
// Save token for later use // Save token for later use
await CookieService.SetValue("token", token, 30); // TODO: config await CookieService.SetValue("token", token, 30); // TODO: config

View File

@@ -9,7 +9,7 @@
@inject AlertService AlertService @inject AlertService AlertService
@inject IAuthenticationProvider AuthenticationProvider @inject IAuthenticationProvider AuthenticationProvider
@if (IdentityService.CurrentUser.Totp) @if (IdentityService.GetUser().Totp)
{ {
<div class="d-flex justify-content-center flex-column text-center"> <div class="d-flex justify-content-center flex-column text-center">
<div class="d-flex justify-content-center"> <div class="d-flex justify-content-center">
@@ -43,7 +43,7 @@ else
var qrCodeData = qrGenerator.CreateQrCode var qrCodeData = qrGenerator.CreateQrCode
( (
$"otpauth://totp/{Uri.EscapeDataString(IdentityService.CurrentUser.Email)}?secret={Key}&issuer={Uri.EscapeDataString("Moonlight")}", $"otpauth://totp/{Uri.EscapeDataString(IdentityService.GetUser().Email)}?secret={Key}&issuer={Uri.EscapeDataString("Moonlight")}",
QRCodeGenerator.ECCLevel.Q QRCodeGenerator.ECCLevel.Q
); );
@@ -142,8 +142,8 @@ else
private async Task Disable(ConfirmButton _) private async Task Disable(ConfirmButton _)
{ {
await AuthenticationProvider.SetTwoFactorSecret(IdentityService.CurrentUser, ""); await AuthenticationProvider.SetTwoFactorSecret(IdentityService.GetUser(), "");
await IdentityService.Authenticate(true); await IdentityService.Authenticate();
HasStarted = false; HasStarted = false;
HasCompletedAppLinks = false; HasCompletedAppLinks = false;
@@ -177,8 +177,8 @@ else
} }
// Enable two factor auth for user // Enable two factor auth for user
await AuthenticationProvider.SetTwoFactorSecret(IdentityService.CurrentUser, Key); await AuthenticationProvider.SetTwoFactorSecret(IdentityService.GetUser(), Key);
await IdentityService.Authenticate(true); await IdentityService.Authenticate();
HasStarted = false; HasStarted = false;
HasCompletedAppLinks = false; HasCompletedAppLinks = false;

View File

@@ -1,7 +1,6 @@
@using MoonCore.Services @using MoonCore.Services
@using Moonlight.Core.Configuration @using Moonlight.Core.Configuration
@using Moonlight.Core.Services @using Moonlight.Core.Database.Entities
@using IdentityService = Moonlight.Core.Services.IdentityService
@inject IdentityService IdentityService @inject IdentityService IdentityService
@inject ConfigService<CoreConfiguration> ConfigService @inject ConfigService<CoreConfiguration> ConfigService
@@ -13,7 +12,7 @@
var greeting = GetGreetingMessage(); var greeting = GetGreetingMessage();
} }
@greeting.Item1 @greeting.Item1
<span class="text-info">@IdentityService.CurrentUser.Username</span> <span class="text-info">@IdentityService.GetUser().Username</span>
@greeting.Item2 @greeting.Item2
</span> </span>
</div> </div>

View File

@@ -1,6 +1,4 @@
@using Moonlight.Core.Services @inject IdentityService IdentityService
@inject IdentityService IdentityService
@inject CookieService CookieService @inject CookieService CookieService
<div class="app-header d-flex flex-column flex-stack"> <div class="app-header d-flex flex-column flex-stack">
@@ -24,13 +22,13 @@
<ConnectionIndicator/> <ConnectionIndicator/>
</div> </div>
@if (IdentityService.IsLoggedIn) @if (IdentityService.IsAuthenticated)
{ {
<div class="app-navbar-item ms-2 ms-lg-6 me-8"> <div class="app-navbar-item ms-2 ms-lg-6 me-8">
<div class="btn btn-active-light d-flex align-items-center bg-hover-light py-2 px-2 px-md-3" id="dropdownMenuLink" data-bs-toggle="dropdown"> <div class="btn btn-active-light d-flex align-items-center bg-hover-light py-2 px-2 px-md-3" id="dropdownMenuLink" data-bs-toggle="dropdown">
<div class="d-none d-md-flex flex-column align-items-end justify-content-center me-5"> <div class="d-none d-md-flex flex-column align-items-end justify-content-center me-5">
<span class="text-muted fs-7 fw-semibold lh-1 mb-2">Welcome,</span> <span class="text-muted fs-7 fw-semibold lh-1 mb-2">Welcome,</span>
<span class="text-gray-900 fs-base fw-bold lh-1">@@@IdentityService.CurrentUser.Username</span> <span class="text-gray-900 fs-base fw-bold lh-1">@@@IdentityService.GetUser().Username</span>
</div> </div>
<div class="symbol symbol-30px symbol-md-40px"> <div class="symbol symbol-30px symbol-md-40px">
@@ -46,10 +44,10 @@
</div> </div>
<div class="d-flex flex-column"> <div class="d-flex flex-column">
<div class="fw-bold d-flex align-items-center fs-5"> <div class="fw-bold d-flex align-items-center fs-5">
@IdentityService.CurrentUser.Username @IdentityService.GetUser().Username
</div> </div>
<span class="fw-semibold text-muted fs-7"> <span class="fw-semibold text-muted fs-7">
@IdentityService.CurrentUser.Email @IdentityService.GetUser().Email
</span> </span>
</div> </div>
</div> </div>
@@ -80,7 +78,7 @@
protected override Task OnAfterRenderAsync(bool firstRender) protected override Task OnAfterRenderAsync(bool firstRender)
{ {
if (firstRender) if (firstRender)
IdentityService.OnAuthenticationStateChanged += OnAuthenticationStateChanged; IdentityService.OnStateChanged += OnAuthenticationStateChanged;
return Task.CompletedTask; return Task.CompletedTask;
} }
@@ -96,6 +94,6 @@
await CookieService.SetValue("token", "", 30); await CookieService.SetValue("token", "", 30);
// Reset token in identity service // Reset token in identity service
await IdentityService.Authenticate(""); await IdentityService.Logout();
} }
} }

View File

@@ -56,13 +56,13 @@
} }
} }
@if (IdentityService.IsLoggedIn && IdentityService.CurrentUser.Permissions > 0) @if (IdentityService.IsAuthenticated && IdentityService.GetUser().Permissions > 0)
{ {
<div class="menu-item my-5"> <div class="menu-item my-5">
<div class="app-sidebar-separator separator"></div> <div class="app-sidebar-separator separator"></div>
</div> </div>
@foreach (var sidebarItem in FeatureService.UiContext.SidebarItems.Where(x => x.IsAdmin).OrderBy(x => x.Index).ToArray()) foreach (var sidebarItem in FeatureService.UiContext.SidebarItems.Where(x => x.IsAdmin).OrderBy(x => x.Index).ToArray())
{ {
if (IsMatch(sidebarItem)) if (IsMatch(sidebarItem))
{ {

View File

@@ -1,8 +1,4 @@
@using ApexCharts @using Moonlight.Core.Configuration
@using MoonCore.Services
@using Moonlight.Core.Configuration
@using Moonlight.Core.Services
@using IdentityService = Moonlight.Core.Services.IdentityService
@inject ConfigService<CoreConfiguration> ConfigService @inject ConfigService<CoreConfiguration> ConfigService
@inject IdentityService IdentityService @inject IdentityService IdentityService
@@ -13,17 +9,17 @@
<div style="pointer-events: all; max-width: var(--bs-breakpoint-sm)" class="w-100"> <div style="pointer-events: all; max-width: var(--bs-breakpoint-sm)" class="w-100">
<div class="card shadow-lg"> <div class="card shadow-lg">
<div class="card-body"> <div class="card-body">
<h3 class="mb-4">@ConfigService.Get().Customisation.CookieConsentBanner.BannerTitle</h3> <h3 class="mb-4">@BannerTitle</h3>
<p class="text-muted fs-6"> <p class="text-muted fs-6">
@ConfigService.Get().Customisation.CookieConsentBanner.BannerText @BannerText
</p> </p>
<span class="d-flex gap-5"> <span class="d-flex gap-5">
<a @onclick:preventDefault @onclick="Consent" class="btn btn-primary btn-sm cursor-pointer"> <WButton OnClick="() => SetAnswer(true)" CssClasses="btn btn-primary btn-smr">
<i class="bx bx-check"></i> @ConfigService.Get().Customisation.CookieConsentBanner.ConsentText <i class="bx bx-check"></i> @ConsentText
</a> </WButton>
<a @onclick:preventDefault @onclick="Decline" class="btn btn-secondary btn-sm cursor-pointer"> <WButton OnClick="() => SetAnswer(false)" CssClasses="btn btn-secondary btn-sm cursor-pointer">
<i class="bx bx-x"></i> @ConfigService.Get().Customisation.CookieConsentBanner.DeclineText <i class="bx bx-x"></i> @DeclineText
</a> </WButton>
</span> </span>
</div> </div>
</div> </div>
@@ -31,16 +27,31 @@
</div> </div>
} }
@code { @code
{
private bool ShowBanner; private bool ShowBanner;
private string BannerTitle;
private string BannerText;
private string ConsentText;
private string DeclineText;
protected override void OnInitialized()
{
var config = ConfigService.Get().Customisation.CookieConsentBanner;
BannerTitle = config.BannerTitle;
BannerText = config.BannerText;
ConsentText = config.ConsentText;
DeclineText = config.DeclineText;
}
protected override async Task OnAfterRenderAsync(bool firstRender) protected override async Task OnAfterRenderAsync(bool firstRender)
{ {
if (firstRender) if (firstRender)
{ {
var userWasAsked = await IdentityService.HasFlag("CookieAsked"); var userWasAsked = await IdentityService.HasFlag("CookieAsked");
if (ConfigService.Get().Customisation.CookieConsentBanner.Enabled && !userWasAsked) if (ConfigService.Get().Customisation.CookieConsentBanner.Enabled && !userWasAsked)
ShowBanner = true; ShowBanner = true;
@@ -48,25 +59,16 @@
} }
} }
private async Task Consent() private async Task SetAnswer(bool answer)
{ {
if (!IdentityService.IsLoggedIn) if (!IdentityService.IsAuthenticated)
return;
await IdentityService.SetFlag("CookieAsked", true);
await IdentityService.SetFlag("CookieConsent", true);
await InvokeAsync(StateHasChanged);
}
private async Task Decline()
{
if (!IdentityService.IsLoggedIn)
return; return;
await IdentityService.SetFlag("CookieAsked", true); await IdentityService.SetFlag("CookieAsked", true);
if (answer)
await IdentityService.SetFlag("CookieConsent", true);
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);
} }
} }

View File

@@ -52,7 +52,7 @@ else
if(permissionRequired == null) if(permissionRequired == null)
continue; continue;
if (IdentityService.CurrentUser.Permissions >= permissionRequired.Level) if (IdentityService.GetUser().Permissions >= permissionRequired.Level)
Allowed = true; Allowed = true;
} }

View File

@@ -10,7 +10,7 @@
@if (Crashed || Exception != null) @if (Crashed || Exception != null)
{ {
if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development" || (IdentityService.IsLoggedIn && IdentityService.CurrentUser.Permissions >= 9000)) if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development" || (IdentityService.IsAuthenticated && IdentityService.GetUser().Permissions >= 9000))
{ {
if (Exception != null) if (Exception != null)
{ {
@@ -75,7 +75,7 @@ else
Exception = exception; Exception = exception;
Crashed = true; Crashed = true;
var username = IdentityService.IsLoggedIn ? IdentityService.CurrentUser.Username : "Guest"; var username = IdentityService.IsAuthenticated ? IdentityService.GetUser().Username : "Guest";
Logger.LogWarning("A crash occured in the view of '{username}': {exception}", username, exception); Logger.LogWarning("A crash occured in the view of '{username}': {exception}", username, exception);
} }

View File

@@ -1,9 +1,7 @@
@using Moonlight.Core.Services @using Moonlight.Core.Services
@using Moonlight.Core.UI.Components.Auth @using Moonlight.Core.UI.Components.Auth
@using MoonCore.Services
@using Moonlight.Core.Configuration @using Moonlight.Core.Configuration
@using Moonlight.Core.Events @using Moonlight.Core.Events
@using IdentityService = Moonlight.Core.Services.IdentityService
@inherits LayoutComponentBase @inherits LayoutComponentBase
@@ -27,7 +25,7 @@
<AppHeader/> <AppHeader/>
<div class="app-wrapper flex-column flex-row-fluid"> <div class="app-wrapper flex-column flex-row-fluid">
@if (IdentityService.IsLoggedIn) @if (IdentityService.IsAuthenticated)
{ {
<AppSidebar/> <AppSidebar/>
} }
@@ -54,7 +52,7 @@
{ {
if (IsInitialized) if (IsInitialized)
{ {
if (IdentityService.IsLoggedIn) if (IdentityService.IsAuthenticated)
{ {
<PermissionChecker> <PermissionChecker>
@Body @Body
@@ -115,7 +113,7 @@
// Base init // Base init
await lazyLoader.SetText("Initializing"); await lazyLoader.SetText("Initializing");
IdentityService.OnAuthenticationStateChanged += OnAuthenticationStateChanged; IdentityService.OnStateChanged += OnAuthenticationStateChanged;
CoreEvents.OnMoonlightRestart += async () => CoreEvents.OnMoonlightRestart += async () =>
{ {

View File

@@ -10,7 +10,7 @@
<span class="fs-2 fw-semibold"> <span class="fs-2 fw-semibold">
@* the @@@ looks weird, ik that, it will result in @username *@ @* the @@@ looks weird, ik that, it will result in @username *@
@@@IdentityService.CurrentUser.Username @@@IdentityService.GetUser().Username
</span> </span>
</div> </div>
</div> </div>

View File

@@ -17,7 +17,7 @@
<span class="fs-2 fw-semibold"> <span class="fs-2 fw-semibold">
@* the @@@ looks weird, ik that, it will result in @username *@ @* the @@@ looks weird, ik that, it will result in @username *@
@@@IdentityService.CurrentUser.Username @@@IdentityService.GetUser().Username
</span> </span>
</div> </div>
</div> </div>
@@ -43,7 +43,7 @@
<div class="col-md-9 col-12"> <div class="col-md-9 col-12">
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
<FastForm @ref="Form" Model="User" OnConfigure="OnConfigure" /> <FastForm @ref="Form" Model="Model" OnConfigure="OnConfigure" />
</div> </div>
<div class="card-footer d-flex justify-content-end"> <div class="card-footer d-flex justify-content-end">
<WButton OnClick="SaveChanges" CssClasses="btn btn-primary">Save changes</WButton> <WButton OnClick="SaveChanges" CssClasses="btn btn-primary">Save changes</WButton>
@@ -54,16 +54,16 @@
@code @code
{ {
private User User; private UpdateAccountForm Model;
private FastForm<User> Form; private FastForm<UpdateAccountForm> Form;
protected override void OnInitialized() protected override void OnInitialized()
{ {
// Create a copy of the user // Create a copy of the user
User = Mapper.Map<User>(IdentityService.CurrentUser); Model = Mapper.Map<UpdateAccountForm>(IdentityService.GetUser());
} }
private void OnConfigure(FastFormConfiguration<User> configuration) private void OnConfigure(FastFormConfiguration<UpdateAccountForm> configuration)
{ {
configuration.AddProperty(x => x.Username) configuration.AddProperty(x => x.Username)
.WithComponent<StringComponent>(component => .WithComponent<StringComponent>(component =>
@@ -90,10 +90,10 @@
if(!await Form.Submit()) if(!await Form.Submit())
return; return;
await AuthenticationProvider.ChangeDetails(IdentityService.CurrentUser, User.Email, User.Username); await AuthenticationProvider.ChangeDetails(IdentityService.GetUser(), Model.Email, Model.Username);
await ToastService.Success("Successfully updated details"); await ToastService.Success("Successfully updated details");
// This will trigger a re-render as well as an update of the model // This will trigger a re-render as well as an update of the model
await IdentityService.Authenticate(true); await IdentityService.Authenticate();
} }
} }

View File

@@ -17,7 +17,7 @@
<span class="fs-2 fw-semibold"> <span class="fs-2 fw-semibold">
@* the @@@ looks weird, ik that, it will result in @username *@ @* the @@@ looks weird, ik that, it will result in @username *@
@@@IdentityService.CurrentUser.Username @@@IdentityService.GetUser().Username
</span> </span>
</div> </div>
</div> </div>
@@ -112,9 +112,9 @@
if (PasswordModel.Password != PasswordModel.RepeatedPassword) if (PasswordModel.Password != PasswordModel.RepeatedPassword)
throw new DisplayException("The passwords do not match"); throw new DisplayException("The passwords do not match");
await AuthenticationProvider.ChangePassword(IdentityService.CurrentUser, PasswordModel.Password); await AuthenticationProvider.ChangePassword(IdentityService.GetUser(), PasswordModel.Password);
await ToastService.Success("Successfully changed password"); await ToastService.Success("Successfully changed password");
await IdentityService.Authenticate(true); await IdentityService.Authenticate();
} }
} }

View File

@@ -12,7 +12,7 @@
<div class="row mb-8 gap-4"> <div class="row mb-8 gap-4">
@foreach (var column in Columns.OrderBy(x => x.Index)) @foreach (var column in Columns.OrderBy(x => x.Index))
{ {
if (column.RequiredPermissionLevel <= IdentityService.CurrentUser.Permissions) if (column.RequiredPermissionLevel <= IdentityService.GetUser().Permissions)
{ {
<div class="col-12 col-lg-6 col-xl"> <div class="col-12 col-lg-6 col-xl">
@column.Component @column.Component
@@ -22,7 +22,7 @@
</div> </div>
@foreach (var component in Components.OrderBy(x => x.Index)) @foreach (var component in Components.OrderBy(x => x.Index))
{ {
if (component.RequiredPermissionLevel <= IdentityService.CurrentUser.Permissions) if (component.RequiredPermissionLevel <= IdentityService.GetUser().Permissions)
{ {
<div class="mb-4"> <div class="mb-4">
@component.Component @component.Component

View File

@@ -29,10 +29,12 @@
PageSize="50"> PageSize="50">
<MCBColumn TItem="Session" Title="User" Field="@(x => x.CreatedAt)"> <MCBColumn TItem="Session" Title="User" Field="@(x => x.CreatedAt)">
<Template> <Template>
@if (context.IdentityService.IsLoggedIn) @if (context.IdentityService.IsAuthenticated)
{ {
<a target="_blank" href="/admin/users/view/@(context.IdentityService.CurrentUser.Id)"> var user = context.IdentityService.GetUser();
@(context.IdentityService.CurrentUser.Email)
<a target="_blank" href="/admin/users/view/@(user.Id)">
@(user.Email)
</a> </a>
} }
else else

View File

@@ -9,7 +9,7 @@
<LazyLoader Load="Load"> <LazyLoader Load="Load">
@foreach (var component in Components.OrderBy(x => x.Index)) @foreach (var component in Components.OrderBy(x => x.Index))
{ {
if (component.RequiredPermissionLevel <= IdentityService.CurrentUser.Permissions) if (component.RequiredPermissionLevel <= IdentityService.GetUser().Permissions)
{ {
<div class="mb-4"> <div class="mb-4">
@component.Component @component.Component

View File

@@ -32,8 +32,8 @@
{ {
if (firstRender) if (firstRender)
{ {
ServerCount = await ServerRepository.Get().Where(x => x.Owner == IdentityService.CurrentUser).CountAsync(); ServerCount = await ServerRepository.Get().Where(x => x.Owner == IdentityService.GetUser()).CountAsync();
NetworksCount = await NetworkRepository.Get().Where(x => x.User == IdentityService.CurrentUser).CountAsync(); NetworksCount = await NetworkRepository.Get().Where(x => x.User == IdentityService.GetUser()).CountAsync();
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);
} }
} }

View File

@@ -3,7 +3,6 @@
@using Moonlight.Features.Servers.Services @using Moonlight.Features.Servers.Services
@using Moonlight.Features.Servers.UI.Components @using Moonlight.Features.Servers.UI.Components
@using MoonCore.Abstractions @using MoonCore.Abstractions
@using MoonCore.Helpers
@using Microsoft.EntityFrameworkCore @using Microsoft.EntityFrameworkCore
@using Moonlight.Features.Servers.Helpers @using Moonlight.Features.Servers.Helpers
@using Moonlight.Features.Servers.UI.UserViews @using Moonlight.Features.Servers.UI.UserViews
@@ -11,8 +10,6 @@
@using System.Net.WebSockets @using System.Net.WebSockets
@using MoonCore.Exceptions @using MoonCore.Exceptions
@using Moonlight.Features.Servers.Configuration @using Moonlight.Features.Servers.Configuration
@using MoonCore.Services
@using IdentityService = Moonlight.Core.Services.IdentityService
@using MoonCore.Blazor.Forms.Router @using MoonCore.Blazor.Forms.Router
@inject Repository<Server> ServerRepository @inject Repository<Server> ServerRepository
@@ -226,7 +223,7 @@
.Include(x => x.Owner) .Include(x => x.Owner)
.First(x => x.Id == Id); .First(x => x.Id == Id);
if (Server.Owner.Id != IdentityService.CurrentUser.Id && IdentityService.CurrentUser.Permissions < 5000) if (Server.Owner.Id != IdentityService.GetUser().Id && IdentityService.GetUser().Permissions < 5000)
{ {
Server = null!; Server = null!;
return; return;

View File

@@ -1,8 +1,5 @@
@using Moonlight.Features.Servers.Entities @using Moonlight.Features.Servers.Entities
@using MoonCore.Services
@using Moonlight.Core.Configuration @using Moonlight.Core.Configuration
@using Moonlight.Core.Services
@using IdentityService = Moonlight.Core.Services.IdentityService
@inject ConfigService<CoreConfiguration> ConfigService @inject ConfigService<CoreConfiguration> ConfigService
@inject IdentityService IdentityService @inject IdentityService IdentityService
@@ -37,6 +34,6 @@
$"--use-ftp-port {Node.FtpPort} " + $"--use-ftp-port {Node.FtpPort} " +
$"--use-fqdn {Node.Fqdn} " + $"--use-fqdn {Node.Fqdn} " +
$"--use-ssl {Node.Ssl.ToString().ToLower()} " + $"--use-ssl {Node.Ssl.ToString().ToLower()} " +
$"--use-email {IdentityService.CurrentUser.Email}"; $"--use-email {IdentityService.GetUser().Email}";
} }
} }

View File

@@ -143,7 +143,7 @@
.Include(x => x.MainAllocation) .Include(x => x.MainAllocation)
.Include(x => x.Node) .Include(x => x.Node)
.Include(x => x.Image) .Include(x => x.Image)
.Where(x => x.Owner.Id == IdentityService.CurrentUser.Id) .Where(x => x.Owner.Id == IdentityService.GetUser().Id)
.ToArray(); .ToArray();
Task.Run(async () => Task.Run(async () =>

View File

@@ -51,7 +51,7 @@
var result = repository var result = repository
.Get() .Get()
.Include(x => x.Node) .Include(x => x.Node)
.Where(x => x.User.Id == IdentityService.CurrentUser.Id); .Where(x => x.User.Id == IdentityService.GetUser().Id);
UsedByCache.Clear(); UsedByCache.Clear();
@@ -60,7 +60,7 @@
var serversUsingThisNetwork = ServerRepository var serversUsingThisNetwork = ServerRepository
.Get() .Get()
.Where(x => x.Network.Id == network.Id) .Where(x => x.Network.Id == network.Id)
.Where(x => x.Owner.Id == IdentityService.CurrentUser.Id) .Where(x => x.Owner.Id == IdentityService.GetUser().Id)
.ToArray(); .ToArray();
UsedByCache.Add(network.Id, serversUsingThisNetwork); UsedByCache.Add(network.Id, serversUsingThisNetwork);
@@ -75,7 +75,7 @@
{ {
if (!ServerRepository if (!ServerRepository
.Get() .Get()
.Any(x => x.Node.Id == network.Node.Id && x.Owner.Id == IdentityService.CurrentUser.Id)) .Any(x => x.Node.Id == network.Node.Id && x.Owner.Id == IdentityService.GetUser().Id))
{ {
throw new DisplayException("You need a server on the selected node in order to create a network on the node"); throw new DisplayException("You need a server on the selected node in order to create a network on the node");
} }
@@ -83,7 +83,7 @@
//TODO: Add config to check the amount of networks created //TODO: Add config to check the amount of networks created
// Set user as the crud is not allowed to set it (user crud and so on) // Set user as the crud is not allowed to set it (user crud and so on)
network.User = IdentityService.CurrentUser; network.User = IdentityService.GetUser();
return Task.CompletedTask; return Task.CompletedTask;
}; };

View File

@@ -3,6 +3,9 @@
@using Microsoft.JSInterop @using Microsoft.JSInterop
@using Moonlight @using Moonlight
@using MoonCore.Services
@using MoonCore.Helpers
@using MoonCore.Blazor.Components @using MoonCore.Blazor.Components
@using MoonCore.Blazor.Forms @using MoonCore.Blazor.Forms
@using MoonCore.Blazor.Services @using MoonCore.Blazor.Services
@@ -16,6 +19,7 @@
@using Moonlight.Core.UI @using Moonlight.Core.UI
@using Moonlight.Core.Attributes @using Moonlight.Core.Attributes
@using Moonlight.Core.Extensions
@using Moonlight.Core.UI.Components @using Moonlight.Core.UI.Components
@using Moonlight.Core.UI.Components.Partials @using Moonlight.Core.UI.Components.Partials
@using Moonlight.Core.UI.Components.Alerts @using Moonlight.Core.UI.Components.Alerts