Switched to new mooncore authentication service
This commit is contained in:
@@ -90,6 +90,16 @@ public class CoreConfiguration
|
||||
[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")]
|
||||
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
|
||||
|
||||
@@ -26,7 +26,7 @@ using Moonlight.Core.Implementations.AdminDashboard;
|
||||
using Moonlight.Core.Implementations.ApiDefinition;
|
||||
using Moonlight.Core.Implementations.UserDashboard;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
using IdentityService = Moonlight.Core.Services.IdentityService;
|
||||
using AuthenticationStateProvider = Moonlight.Core.Helpers.AuthenticationStateProvider;
|
||||
|
||||
namespace Moonlight.Core;
|
||||
|
||||
@@ -68,6 +68,9 @@ public class CoreFeature : MoonlightFeature
|
||||
builder.Services.AddMoonCore(configuration =>
|
||||
{
|
||||
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();
|
||||
|
||||
54
Moonlight/Core/Extensions/IdentityServiceExtensions.cs
Normal file
54
Moonlight/Core/Extensions/IdentityServiceExtensions.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
50
Moonlight/Core/Helpers/AuthenticationStateProvider.cs
Normal file
50
Moonlight/Core/Helpers/AuthenticationStateProvider.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,11 @@
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using MoonCore.Abstractions;
|
||||
using MoonCore.Helpers;
|
||||
using MoonCore.Services;
|
||||
using Moonlight.Core.Attributes;
|
||||
using Moonlight.Core.Configuration;
|
||||
using Moonlight.Core.Database.Entities;
|
||||
using Moonlight.Core.Services;
|
||||
using IdentityService = Moonlight.Core.Services.IdentityService;
|
||||
using Moonlight.Core.Extensions;
|
||||
|
||||
namespace Moonlight.Core.Http.Controllers;
|
||||
|
||||
@@ -42,10 +40,10 @@ public class AvatarController : Controller
|
||||
var token = Request.Cookies["token"];
|
||||
await IdentityService.Authenticate(token!);
|
||||
|
||||
if (!IdentityService.IsLoggedIn)
|
||||
if (!IdentityService.IsAuthenticated)
|
||||
return StatusCode(403);
|
||||
|
||||
return File(await GetAvatar(IdentityService.CurrentUser), "image/jpeg");
|
||||
return File(await GetAvatar(IdentityService.GetUser()), "image/jpeg");
|
||||
}
|
||||
|
||||
[HttpGet("{id:int}")]
|
||||
@@ -57,12 +55,12 @@ public class AvatarController : Controller
|
||||
var token = Request.Cookies["token"];
|
||||
await IdentityService.Authenticate(token!);
|
||||
|
||||
if (!IdentityService.IsLoggedIn)
|
||||
if (!IdentityService.IsAuthenticated)
|
||||
return StatusCode(403);
|
||||
|
||||
if (ConfigService.Get().Security.EnforceAvatarPrivacy && // Do we need to enforce privacy?
|
||||
id != IdentityService.CurrentUser.Id && // is the user not viewing his own image?
|
||||
IdentityService.CurrentUser.Permissions < 1000) // and not an admin?
|
||||
id != IdentityService.GetUser().Id && // is the user not viewing his own image?
|
||||
IdentityService.GetUser().Permissions < 1000) // and not an admin?
|
||||
{
|
||||
return StatusCode(403);
|
||||
}
|
||||
|
||||
@@ -4,12 +4,6 @@ namespace Moonlight.Core.Models.Forms;
|
||||
|
||||
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; }
|
||||
|
||||
[Required(ErrorMessage = "You need to provide an email address")]
|
||||
[EmailAddress(ErrorMessage = "You need to enter a valid email address")]
|
||||
public string Email { get; set; } = "";
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using MoonCore.Blazor.Services;
|
||||
using Moonlight.Core.Services;
|
||||
using MoonCore.Services;
|
||||
|
||||
namespace Moonlight.Core.Models;
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -3,13 +3,14 @@
|
||||
|
||||
@using Moonlight.Core.Models.Abstractions
|
||||
@using Moonlight.Core.Models.Forms
|
||||
@using Moonlight.Core.Services
|
||||
@using MoonCore.Exceptions
|
||||
@using Moonlight.Core.Configuration
|
||||
|
||||
@inject IAuthenticationProvider AuthenticationProvider
|
||||
@inject IdentityService IdentityService
|
||||
@inject CookieService CookieService
|
||||
@inject NavigationManager Navigation
|
||||
@inject ConfigService<CoreConfiguration> ConfigService
|
||||
|
||||
<div class="d-flex justify-content-center">
|
||||
<div class="d-flex align-items-center">
|
||||
@@ -89,7 +90,10 @@
|
||||
throw new DisplayException("A user with these credential combination was not found");
|
||||
|
||||
// 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
|
||||
await CookieService.SetValue("token", token, 30); //TODO: Add days to config option
|
||||
|
||||
@@ -4,11 +4,8 @@
|
||||
|
||||
@using Moonlight.Core.Models.Abstractions
|
||||
@using Moonlight.Core.Models.Forms
|
||||
@using Moonlight.Core.Services
|
||||
@using MoonCore.Exceptions
|
||||
@using MoonCore.Services
|
||||
@using Moonlight.Core.Configuration
|
||||
@using IdentityService = Moonlight.Core.Services.IdentityService
|
||||
|
||||
@inject IAuthenticationProvider AuthenticationProvider
|
||||
@inject IdentityService IdentityService
|
||||
@@ -96,7 +93,10 @@
|
||||
throw new DisplayException("Unable to create account");
|
||||
|
||||
// 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
|
||||
await CookieService.SetValue("token", token, 30); // TODO: config
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
@inject AlertService AlertService
|
||||
@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">
|
||||
@@ -43,7 +43,7 @@ else
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
@@ -142,8 +142,8 @@ else
|
||||
|
||||
private async Task Disable(ConfirmButton _)
|
||||
{
|
||||
await AuthenticationProvider.SetTwoFactorSecret(IdentityService.CurrentUser, "");
|
||||
await IdentityService.Authenticate(true);
|
||||
await AuthenticationProvider.SetTwoFactorSecret(IdentityService.GetUser(), "");
|
||||
await IdentityService.Authenticate();
|
||||
|
||||
HasStarted = false;
|
||||
HasCompletedAppLinks = false;
|
||||
@@ -177,8 +177,8 @@ else
|
||||
}
|
||||
|
||||
// Enable two factor auth for user
|
||||
await AuthenticationProvider.SetTwoFactorSecret(IdentityService.CurrentUser, Key);
|
||||
await IdentityService.Authenticate(true);
|
||||
await AuthenticationProvider.SetTwoFactorSecret(IdentityService.GetUser(), Key);
|
||||
await IdentityService.Authenticate();
|
||||
|
||||
HasStarted = false;
|
||||
HasCompletedAppLinks = false;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
@using MoonCore.Services
|
||||
@using Moonlight.Core.Configuration
|
||||
@using Moonlight.Core.Services
|
||||
@using IdentityService = Moonlight.Core.Services.IdentityService
|
||||
@using Moonlight.Core.Database.Entities
|
||||
|
||||
@inject IdentityService IdentityService
|
||||
@inject ConfigService<CoreConfiguration> ConfigService
|
||||
@@ -13,7 +12,7 @@
|
||||
var greeting = GetGreetingMessage();
|
||||
}
|
||||
@greeting.Item1
|
||||
<span class="text-info">@IdentityService.CurrentUser.Username</span>
|
||||
<span class="text-info">@IdentityService.GetUser().Username</span>
|
||||
@greeting.Item2
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
@using Moonlight.Core.Services
|
||||
|
||||
@inject IdentityService IdentityService
|
||||
@inject IdentityService IdentityService
|
||||
@inject CookieService CookieService
|
||||
|
||||
<div class="app-header d-flex flex-column flex-stack">
|
||||
@@ -24,13 +22,13 @@
|
||||
<ConnectionIndicator/>
|
||||
</div>
|
||||
|
||||
@if (IdentityService.IsLoggedIn)
|
||||
@if (IdentityService.IsAuthenticated)
|
||||
{
|
||||
<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="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-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 class="symbol symbol-30px symbol-md-40px">
|
||||
@@ -46,10 +44,10 @@
|
||||
</div>
|
||||
<div class="d-flex flex-column">
|
||||
<div class="fw-bold d-flex align-items-center fs-5">
|
||||
@IdentityService.CurrentUser.Username
|
||||
@IdentityService.GetUser().Username
|
||||
</div>
|
||||
<span class="fw-semibold text-muted fs-7">
|
||||
@IdentityService.CurrentUser.Email
|
||||
@IdentityService.GetUser().Email
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -80,7 +78,7 @@
|
||||
protected override Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
IdentityService.OnAuthenticationStateChanged += OnAuthenticationStateChanged;
|
||||
IdentityService.OnStateChanged += OnAuthenticationStateChanged;
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
@@ -96,6 +94,6 @@
|
||||
await CookieService.SetValue("token", "", 30);
|
||||
|
||||
// Reset token in identity service
|
||||
await IdentityService.Authenticate("");
|
||||
await IdentityService.Logout();
|
||||
}
|
||||
}
|
||||
@@ -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="app-sidebar-separator separator"></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))
|
||||
{
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
@using ApexCharts
|
||||
@using MoonCore.Services
|
||||
@using Moonlight.Core.Configuration
|
||||
@using Moonlight.Core.Services
|
||||
@using IdentityService = Moonlight.Core.Services.IdentityService
|
||||
@using Moonlight.Core.Configuration
|
||||
|
||||
@inject ConfigService<CoreConfiguration> ConfigService
|
||||
@inject IdentityService IdentityService
|
||||
@@ -13,17 +9,17 @@
|
||||
<div style="pointer-events: all; max-width: var(--bs-breakpoint-sm)" class="w-100">
|
||||
<div class="card shadow-lg">
|
||||
<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">
|
||||
@ConfigService.Get().Customisation.CookieConsentBanner.BannerText
|
||||
@BannerText
|
||||
</p>
|
||||
<span class="d-flex gap-5">
|
||||
<a @onclick:preventDefault @onclick="Consent" class="btn btn-primary btn-sm cursor-pointer">
|
||||
<i class="bx bx-check"></i> @ConfigService.Get().Customisation.CookieConsentBanner.ConsentText
|
||||
</a>
|
||||
<a @onclick:preventDefault @onclick="Decline" class="btn btn-secondary btn-sm cursor-pointer">
|
||||
<i class="bx bx-x"></i> @ConfigService.Get().Customisation.CookieConsentBanner.DeclineText
|
||||
</a>
|
||||
<WButton OnClick="() => SetAnswer(true)" CssClasses="btn btn-primary btn-smr">
|
||||
<i class="bx bx-check"></i> @ConsentText
|
||||
</WButton>
|
||||
<WButton OnClick="() => SetAnswer(false)" CssClasses="btn btn-secondary btn-sm cursor-pointer">
|
||||
<i class="bx bx-x"></i> @DeclineText
|
||||
</WButton>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -31,10 +27,25 @@
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
|
||||
@code
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (firstRender)
|
||||
@@ -48,25 +59,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
private async Task Consent()
|
||||
private async Task SetAnswer(bool answer)
|
||||
{
|
||||
if (!IdentityService.IsLoggedIn)
|
||||
return;
|
||||
|
||||
await IdentityService.SetFlag("CookieAsked", true);
|
||||
await IdentityService.SetFlag("CookieConsent", true);
|
||||
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
private async Task Decline()
|
||||
{
|
||||
if (!IdentityService.IsLoggedIn)
|
||||
if (!IdentityService.IsAuthenticated)
|
||||
return;
|
||||
|
||||
await IdentityService.SetFlag("CookieAsked", true);
|
||||
|
||||
if (answer)
|
||||
await IdentityService.SetFlag("CookieConsent", true);
|
||||
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -52,7 +52,7 @@ else
|
||||
if(permissionRequired == null)
|
||||
continue;
|
||||
|
||||
if (IdentityService.CurrentUser.Permissions >= permissionRequired.Level)
|
||||
if (IdentityService.GetUser().Permissions >= permissionRequired.Level)
|
||||
Allowed = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
@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)
|
||||
{
|
||||
@@ -75,7 +75,7 @@ else
|
||||
Exception = exception;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
@using Moonlight.Core.Services
|
||||
@using Moonlight.Core.UI.Components.Auth
|
||||
@using MoonCore.Services
|
||||
@using Moonlight.Core.Configuration
|
||||
@using Moonlight.Core.Events
|
||||
@using IdentityService = Moonlight.Core.Services.IdentityService
|
||||
|
||||
@inherits LayoutComponentBase
|
||||
|
||||
@@ -27,7 +25,7 @@
|
||||
<AppHeader/>
|
||||
|
||||
<div class="app-wrapper flex-column flex-row-fluid">
|
||||
@if (IdentityService.IsLoggedIn)
|
||||
@if (IdentityService.IsAuthenticated)
|
||||
{
|
||||
<AppSidebar/>
|
||||
}
|
||||
@@ -54,7 +52,7 @@
|
||||
{
|
||||
if (IsInitialized)
|
||||
{
|
||||
if (IdentityService.IsLoggedIn)
|
||||
if (IdentityService.IsAuthenticated)
|
||||
{
|
||||
<PermissionChecker>
|
||||
@Body
|
||||
@@ -115,7 +113,7 @@
|
||||
// Base init
|
||||
await lazyLoader.SetText("Initializing");
|
||||
|
||||
IdentityService.OnAuthenticationStateChanged += OnAuthenticationStateChanged;
|
||||
IdentityService.OnStateChanged += OnAuthenticationStateChanged;
|
||||
|
||||
CoreEvents.OnMoonlightRestart += async () =>
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<span class="fs-2 fw-semibold">
|
||||
@* the @@@ looks weird, ik that, it will result in @username *@
|
||||
|
||||
@@@IdentityService.CurrentUser.Username
|
||||
@@@IdentityService.GetUser().Username
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<span class="fs-2 fw-semibold">
|
||||
@* the @@@ looks weird, ik that, it will result in @username *@
|
||||
|
||||
@@@IdentityService.CurrentUser.Username
|
||||
@@@IdentityService.GetUser().Username
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -43,7 +43,7 @@
|
||||
<div class="col-md-9 col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<FastForm @ref="Form" Model="User" OnConfigure="OnConfigure" />
|
||||
<FastForm @ref="Form" Model="Model" OnConfigure="OnConfigure" />
|
||||
</div>
|
||||
<div class="card-footer d-flex justify-content-end">
|
||||
<WButton OnClick="SaveChanges" CssClasses="btn btn-primary">Save changes</WButton>
|
||||
@@ -54,16 +54,16 @@
|
||||
|
||||
@code
|
||||
{
|
||||
private User User;
|
||||
private FastForm<User> Form;
|
||||
private UpdateAccountForm Model;
|
||||
private FastForm<UpdateAccountForm> Form;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
// 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)
|
||||
.WithComponent<StringComponent>(component =>
|
||||
@@ -90,10 +90,10 @@
|
||||
if(!await Form.Submit())
|
||||
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");
|
||||
|
||||
// This will trigger a re-render as well as an update of the model
|
||||
await IdentityService.Authenticate(true);
|
||||
await IdentityService.Authenticate();
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
<span class="fs-2 fw-semibold">
|
||||
@* the @@@ looks weird, ik that, it will result in @username *@
|
||||
|
||||
@@@IdentityService.CurrentUser.Username
|
||||
@@@IdentityService.GetUser().Username
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -112,9 +112,9 @@
|
||||
if (PasswordModel.Password != PasswordModel.RepeatedPassword)
|
||||
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 IdentityService.Authenticate(true);
|
||||
await IdentityService.Authenticate();
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
<div class="row mb-8 gap-4">
|
||||
@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">
|
||||
@column.Component
|
||||
@@ -22,7 +22,7 @@
|
||||
</div>
|
||||
@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">
|
||||
@component.Component
|
||||
|
||||
@@ -29,10 +29,12 @@
|
||||
PageSize="50">
|
||||
<MCBColumn TItem="Session" Title="User" Field="@(x => x.CreatedAt)">
|
||||
<Template>
|
||||
@if (context.IdentityService.IsLoggedIn)
|
||||
@if (context.IdentityService.IsAuthenticated)
|
||||
{
|
||||
<a target="_blank" href="/admin/users/view/@(context.IdentityService.CurrentUser.Id)">
|
||||
@(context.IdentityService.CurrentUser.Email)
|
||||
var user = context.IdentityService.GetUser();
|
||||
|
||||
<a target="_blank" href="/admin/users/view/@(user.Id)">
|
||||
@(user.Email)
|
||||
</a>
|
||||
}
|
||||
else
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<LazyLoader Load="Load">
|
||||
@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">
|
||||
@component.Component
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
ServerCount = await ServerRepository.Get().Where(x => x.Owner == IdentityService.CurrentUser).CountAsync();
|
||||
NetworksCount = await NetworkRepository.Get().Where(x => x.User == IdentityService.CurrentUser).CountAsync();
|
||||
ServerCount = await ServerRepository.Get().Where(x => x.Owner == IdentityService.GetUser()).CountAsync();
|
||||
NetworksCount = await NetworkRepository.Get().Where(x => x.User == IdentityService.GetUser()).CountAsync();
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
@using Moonlight.Features.Servers.Services
|
||||
@using Moonlight.Features.Servers.UI.Components
|
||||
@using MoonCore.Abstractions
|
||||
@using MoonCore.Helpers
|
||||
@using Microsoft.EntityFrameworkCore
|
||||
@using Moonlight.Features.Servers.Helpers
|
||||
@using Moonlight.Features.Servers.UI.UserViews
|
||||
@@ -11,8 +10,6 @@
|
||||
@using System.Net.WebSockets
|
||||
@using MoonCore.Exceptions
|
||||
@using Moonlight.Features.Servers.Configuration
|
||||
@using MoonCore.Services
|
||||
@using IdentityService = Moonlight.Core.Services.IdentityService
|
||||
@using MoonCore.Blazor.Forms.Router
|
||||
|
||||
@inject Repository<Server> ServerRepository
|
||||
@@ -226,7 +223,7 @@
|
||||
.Include(x => x.Owner)
|
||||
.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!;
|
||||
return;
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
@using Moonlight.Features.Servers.Entities
|
||||
@using MoonCore.Services
|
||||
@using Moonlight.Core.Configuration
|
||||
@using Moonlight.Core.Services
|
||||
@using IdentityService = Moonlight.Core.Services.IdentityService
|
||||
|
||||
@inject ConfigService<CoreConfiguration> ConfigService
|
||||
@inject IdentityService IdentityService
|
||||
@@ -37,6 +34,6 @@
|
||||
$"--use-ftp-port {Node.FtpPort} " +
|
||||
$"--use-fqdn {Node.Fqdn} " +
|
||||
$"--use-ssl {Node.Ssl.ToString().ToLower()} " +
|
||||
$"--use-email {IdentityService.CurrentUser.Email}";
|
||||
$"--use-email {IdentityService.GetUser().Email}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
.Include(x => x.MainAllocation)
|
||||
.Include(x => x.Node)
|
||||
.Include(x => x.Image)
|
||||
.Where(x => x.Owner.Id == IdentityService.CurrentUser.Id)
|
||||
.Where(x => x.Owner.Id == IdentityService.GetUser().Id)
|
||||
.ToArray();
|
||||
|
||||
Task.Run(async () =>
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
var result = repository
|
||||
.Get()
|
||||
.Include(x => x.Node)
|
||||
.Where(x => x.User.Id == IdentityService.CurrentUser.Id);
|
||||
.Where(x => x.User.Id == IdentityService.GetUser().Id);
|
||||
|
||||
UsedByCache.Clear();
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
var serversUsingThisNetwork = ServerRepository
|
||||
.Get()
|
||||
.Where(x => x.Network.Id == network.Id)
|
||||
.Where(x => x.Owner.Id == IdentityService.CurrentUser.Id)
|
||||
.Where(x => x.Owner.Id == IdentityService.GetUser().Id)
|
||||
.ToArray();
|
||||
|
||||
UsedByCache.Add(network.Id, serversUsingThisNetwork);
|
||||
@@ -75,7 +75,7 @@
|
||||
{
|
||||
if (!ServerRepository
|
||||
.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");
|
||||
}
|
||||
@@ -83,7 +83,7 @@
|
||||
//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)
|
||||
network.User = IdentityService.CurrentUser;
|
||||
network.User = IdentityService.GetUser();
|
||||
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
@using Microsoft.JSInterop
|
||||
@using Moonlight
|
||||
|
||||
@using MoonCore.Services
|
||||
@using MoonCore.Helpers
|
||||
|
||||
@using MoonCore.Blazor.Components
|
||||
@using MoonCore.Blazor.Forms
|
||||
@using MoonCore.Blazor.Services
|
||||
@@ -16,6 +19,7 @@
|
||||
|
||||
@using Moonlight.Core.UI
|
||||
@using Moonlight.Core.Attributes
|
||||
@using Moonlight.Core.Extensions
|
||||
@using Moonlight.Core.UI.Components
|
||||
@using Moonlight.Core.UI.Components.Partials
|
||||
@using Moonlight.Core.UI.Components.Alerts
|
||||
Reference in New Issue
Block a user