From f61592cb35eb5e7c06619b32c3cb4e9abf5755f0 Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Mon, 29 Jul 2024 16:44:13 +0200 Subject: [PATCH] Register first user as admin --- .../App/API/AppApiController.Account.cs | 36 +++++++++++++------ BTCPayServer/App/API/AppApiController.cs | 7 ++-- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/BTCPayServer/App/API/AppApiController.Account.cs b/BTCPayServer/App/API/AppApiController.Account.cs index cb12f1b94..a8baf0807 100644 --- a/BTCPayServer/App/API/AppApiController.Account.cs +++ b/BTCPayServer/App/API/AppApiController.Account.cs @@ -6,14 +6,12 @@ using System.Threading.Tasks; using BTCPayApp.CommonServer.Models; using BTCPayServer.Abstractions.Constants; using BTCPayServer.Abstractions.Extensions; -using BTCPayServer.Abstractions.Models; using BTCPayServer.Client.Models; using BTCPayServer.Data; using BTCPayServer.Events; using BTCPayServer.Plugins.PointOfSale; using BTCPayServer.Services; using BTCPayServer.Services.Apps; -using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.BearerToken; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -37,33 +35,51 @@ public partial class AppApiController [RateLimitsFilter(ZoneLimits.Login, Scope = RateLimitsScope.RemoteAddress)] public async Task, Ok, EmptyHttpResult, ProblemHttpResult>> Register(SignupRequest signup) { - var policiesSettings = await settingsRepository.GetSettingAsync() ?? new PoliciesSettings(); - if (policiesSettings.LockSubscription) + var policies = await settingsRepository.GetSettingAsync() ?? new PoliciesSettings(); + if (policies.LockSubscription) return TypedResults.Problem("This instance does not allow public user registration", statusCode: 401); var errorMessage = "Invalid signup attempt."; if (ModelState.IsValid) { + var isFirstAdmin = !(await userManager.GetUsersInRoleAsync(Roles.ServerAdmin)).Any(); var user = new ApplicationUser { UserName = signup.Email, Email = signup.Email, - RequiresEmailConfirmation = policiesSettings.RequiresConfirmedEmail, - RequiresApproval = policiesSettings.RequiresUserApproval, - Created = DateTimeOffset.UtcNow + RequiresEmailConfirmation = policies.RequiresConfirmedEmail, + RequiresApproval = policies.RequiresUserApproval, + Created = DateTimeOffset.UtcNow, + Approved = isFirstAdmin // auto-approve first admin and users created by an admin }; + var result = await userManager.CreateAsync(user, signup.Password); if (result.Succeeded) { + if (isFirstAdmin) + { + await roleManager.CreateAsync(new IdentityRole(Roles.ServerAdmin)); + await userManager.AddToRoleAsync(user, Roles.ServerAdmin); + var settings = await settingsRepository.GetSettingAsync() ?? new ThemeSettings(); + if (settings.FirstRun) + { + settings.FirstRun = false; + await settingsRepository.UpdateSetting(settings); + } + + await settingsRepository.FirstAdminRegistered(policies, btcpayOptions.UpdateUrl != null, btcpayOptions.DisableRegistration, logs); + } + eventAggregator.Publish(new UserRegisteredEvent { RequestUri = Request.GetAbsoluteRootUri(), - User = user + User = user, + Admin = isFirstAdmin }); SignInResult? signInResult = null; - var requiresConfirmedEmail = policiesSettings.RequiresConfirmedEmail && !user.EmailConfirmed; - var requiresUserApproval = policiesSettings.RequiresUserApproval && !user.Approved; + var requiresConfirmedEmail = policies.RequiresConfirmedEmail && !user.EmailConfirmed; + var requiresUserApproval = policies.RequiresUserApproval && !user.Approved; if (!requiresConfirmedEmail && !requiresUserApproval) { signInManager.AuthenticationScheme = Scheme; diff --git a/BTCPayServer/App/API/AppApiController.cs b/BTCPayServer/App/API/AppApiController.cs index d6f1d00f8..77806c114 100644 --- a/BTCPayServer/App/API/AppApiController.cs +++ b/BTCPayServer/App/API/AppApiController.cs @@ -5,6 +5,7 @@ using BTCPayApp.CommonServer.Models; using BTCPayServer.Abstractions.Constants; using BTCPayServer.Abstractions.Contracts; using BTCPayServer.Abstractions.Extensions; +using BTCPayServer.Configuration; using BTCPayServer.Data; using BTCPayServer.Fido2; using BTCPayServer.Logging; @@ -18,7 +19,6 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -33,14 +33,15 @@ public partial class AppApiController( EventAggregator eventAggregator, SignInManager signInManager, UserManager userManager, + RoleManager roleManager, TimeProvider timeProvider, - ISettingsRepository settingsRepository, + SettingsRepository settingsRepository, UriResolver uriResolver, DefaultRulesCollection defaultRules, RateFetcher rateFactory, - LinkGenerator linkGenerator, UserLoginCodeService userLoginCodeService, Logs logs, + BTCPayServerOptions btcpayOptions, IOptionsMonitor bearerTokenOptions) : Controller {