diff --git a/Wave/Components/Pages/Admin.razor b/Wave/Components/Pages/Admin.razor index d4e473e..f04fa32 100644 --- a/Wave/Components/Pages/Admin.razor +++ b/Wave/Components/Pages/Admin.razor @@ -5,6 +5,8 @@ @using Wave.Components.Account.Shared @using Wave.Data @using Microsoft.AspNetCore.Authorization +@using Microsoft.Extensions.Caching.Distributed; +@using System.Text; @attribute [Authorize] @inject IdentityUserAccessor UserAccessor @@ -13,6 +15,7 @@ @inject SignInManager SignInManager @inject IdentityRedirectManager RedirectManager @inject IStringLocalizer Localizer +@inject IDistributedCache WaveDistributedCache @(TitlePrefix + Localizer["Title"]) @@ -52,8 +55,8 @@ protected override async Task OnInitializedAsync() { User = await UserAccessor.GetRequiredUserAsync(HttpContext); - string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "admin.txt"); - if (File.Exists(path)) Password = await File.ReadAllTextAsync(path); + Password = await WaveDistributedCache.GetStringAsync("admin_promote_key") + ?? ""; } private async Task Promote() { @@ -76,7 +79,7 @@ } } await UserManager.AddToRoleAsync(User, "Admin"); - File.Delete(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "admin.txt")); + await WaveDistributedCache.RemoveAsync("admin_promote_key"); await SignInManager.RefreshSignInAsync(User); Message = "You have been promoted, this tool is now disabled."; } @@ -84,4 +87,4 @@ private sealed class InputModel { public string Password { get; set; } = string.Empty; } -} \ No newline at end of file +} diff --git a/Wave/Program.cs b/Wave/Program.cs index c69b652..85974a0 100644 --- a/Wave/Program.cs +++ b/Wave/Program.cs @@ -7,8 +7,10 @@ using Microsoft.AspNetCore.Identity.UI.Services; using Microsoft.AspNetCore.StaticFiles; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Options; using StackExchange.Redis; +using System.Text; using Tomlyn.Extensions.Configuration; using Wave.Components; using Wave.Components.Account; @@ -79,7 +81,7 @@ .AddPolicy("ArticleDeletePermissions", p => p.RequireRole("Moderator", "Admin")) .AddPolicy("CategoryManagePermissions", p => p.RequireRole("Admin")) .AddPolicy("RoleAssignPermissions", p => p.RequireRole("Admin")) - + .AddPolicy("ArticleEditOrReviewPermissions", p => p.RequireRole("Author", "Reviewer", "Admin")); builder.Services.AddAuthentication(options => { options.DefaultScheme = IdentityConstants.ApplicationScheme; @@ -90,7 +92,7 @@ #region Identity -string connectionString = builder.Configuration.GetConnectionString("DefaultConnection") +string connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found."); builder.Services.AddDbContextFactory(options => options.UseNpgsql(connectionString)); @@ -116,7 +118,7 @@ builder.Services.Configure(builder.Configuration.GetSection(nameof(Features))); builder.Services.Configure(builder.Configuration.GetSection(nameof(Customization))); -builder.Services.AddCascadingValue("TitlePrefix", +builder.Services.AddCascadingValue("TitlePrefix", sf => (sf.GetService>()?.Value.AppName ?? "Wave") + " - "); var smtpConfig = builder.Configuration.GetSection("Email:Smtp"); @@ -190,10 +192,19 @@ var userManager = scope.ServiceProvider.GetRequiredService>(); if (userManager.GetUsersInRoleAsync("Admin").Result.Any() is false) { - string admin = Guid.NewGuid().ToString("N")[..16]; + IDistributedCache cache = app.Services.GetRequiredService(); + + // Check first wheter the password exists already + string admin = await cache.GetStringAsync("admin_promote_key"); + + // If it does not exist, create a new one and save it to redis + if (string.IsNullOrWhiteSpace(admin)){ + admin = Guid.NewGuid().ToString("N")[..16]; + await cache.SetAsync("admin_promote_key", Encoding.UTF8.GetBytes(admin), new DistributedCacheEntryOptions{}); + } + app.Logger.LogWarning("There is currently no user in your installation with the admin role, " + "go to /Admin and use the following password to self promote your account: {admin}", admin); - File.WriteAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "admin.txt"), admin); } }