Fix unattented admin install
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Composing;
|
||||
@@ -10,7 +11,6 @@ using Umbraco.Cms.Core.Logging;
|
||||
using Umbraco.Cms.Core.Runtime;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Infrastructure.Persistence;
|
||||
using Constants = Umbraco.Cms.Core.Constants;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Runtime
|
||||
{
|
||||
@@ -25,6 +25,7 @@ namespace Umbraco.Cms.Infrastructure.Runtime
|
||||
private readonly IUmbracoDatabaseFactory _databaseFactory;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly IHostingEnvironment _hostingEnvironment;
|
||||
private readonly IServiceScopeFactory _serviceScopeFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CoreRuntime"/> class.
|
||||
@@ -38,7 +39,8 @@ namespace Umbraco.Cms.Infrastructure.Runtime
|
||||
IMainDom mainDom,
|
||||
IUmbracoDatabaseFactory databaseFactory,
|
||||
IEventAggregator eventAggregator,
|
||||
IHostingEnvironment hostingEnvironment)
|
||||
IHostingEnvironment hostingEnvironment,
|
||||
IServiceScopeFactory serviceScopeFactory)
|
||||
{
|
||||
State = state;
|
||||
_loggerFactory = loggerFactory;
|
||||
@@ -49,6 +51,7 @@ namespace Umbraco.Cms.Infrastructure.Runtime
|
||||
_databaseFactory = databaseFactory;
|
||||
_eventAggregator = eventAggregator;
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
_serviceScopeFactory = serviceScopeFactory;
|
||||
_logger = _loggerFactory.CreateLogger<CoreRuntime>();
|
||||
}
|
||||
|
||||
@@ -60,6 +63,8 @@ namespace Umbraco.Cms.Infrastructure.Runtime
|
||||
/// <inheritdoc/>
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
using IServiceScope scope = _serviceScopeFactory.CreateScope();
|
||||
|
||||
StaticApplicationLogging.Initialize(_loggerFactory);
|
||||
|
||||
AppDomain.CurrentDomain.UnhandledException += (_, args) =>
|
||||
|
||||
@@ -198,7 +198,7 @@ namespace Umbraco.Cms.Core
|
||||
Reason = reason;
|
||||
}
|
||||
|
||||
public async void DoUnattendedInstall()
|
||||
public void DoUnattendedInstall()
|
||||
{
|
||||
// unattended install is not enabled
|
||||
if (_globalSettings.InstallUnattended == false) return;
|
||||
@@ -239,7 +239,7 @@ namespace Umbraco.Cms.Core
|
||||
|
||||
// Emit an event with EventAggregator that unattended install completed
|
||||
// Then this event can be listened for and create an unattended user
|
||||
await _eventAggregator.PublishAsync(new UnattendedInstallNotification());
|
||||
_eventAggregator.Publish(new UnattendedInstallNotification());
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -271,7 +271,7 @@ namespace Umbraco.Extensions
|
||||
|
||||
builder.Services.AddUnique<InstallAreaRoutes>();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -298,7 +298,7 @@ namespace Umbraco.Extensions
|
||||
|
||||
public static IUmbracoBuilder AddUnattedInstallCreateUser(this IUmbracoBuilder builder)
|
||||
{
|
||||
builder.AddNotificationHandler<UnattendedInstallNotification, CreateUnattendedUserNotificationHandler>();
|
||||
builder.AddNotificationAsyncHandler<UnattendedInstallNotification, CreateUnattendedUserNotificationHandler>();
|
||||
//builder.AddNotificationHandler<UmbracoApplicationStarting, CreateUnattendedUserNotificationHandler>();
|
||||
return builder;
|
||||
}
|
||||
|
||||
@@ -1,81 +1,99 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Events;
|
||||
using Umbraco.Cms.Core.Models.Membership;
|
||||
using Umbraco.Cms.Core.Security;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Web.Common.Install
|
||||
{
|
||||
public class CreateUnattendedUserNotificationHandler : INotificationHandler<UnattendedInstallNotification>
|
||||
public class CreateUnattendedUserNotificationHandler : INotificationAsyncHandler<UnattendedInstallNotification>
|
||||
{
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
private readonly IUserService _userService;
|
||||
private readonly IServiceScopeFactory _serviceScopeFactory;
|
||||
|
||||
public CreateUnattendedUserNotificationHandler(IOptions<GlobalSettings> globalSettings, IUserService userService)
|
||||
public CreateUnattendedUserNotificationHandler(IOptions<GlobalSettings> globalSettings, IUserService userService, IServiceScopeFactory serviceScopeFactory)
|
||||
{
|
||||
_globalSettings = globalSettings.Value;
|
||||
_userService = userService;
|
||||
_serviceScopeFactory = serviceScopeFactory;
|
||||
}
|
||||
|
||||
/// Listening for when the UnattendedInstallNotification fired after a sucessfulk
|
||||
/// </summary>
|
||||
/// <param name="notification"></param>
|
||||
public async void Handle(UnattendedInstallNotification notification)
|
||||
public async Task HandleAsync(UnattendedInstallNotification notification, CancellationToken cancellationToken)
|
||||
{
|
||||
// Ensure we have the setting enabled (Sanity check)
|
||||
// In theory this should always be true as the event only fired when a sucessfull
|
||||
if (_globalSettings.InstallUnattended == false)
|
||||
return;
|
||||
|
||||
var unattendedName = _globalSettings.UnattendedUserName;
|
||||
var unattendedEmail = _globalSettings.UnattendedUserEmail;
|
||||
var unattendedPassword = _globalSettings.UnattendedUserPassword;
|
||||
// Ensure we have the setting enabled (Sanity check)
|
||||
// In theory this should always be true as the event only fired when a sucessfull
|
||||
if (_globalSettings.InstallUnattended == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Missing configuration values (json, env variables etc)
|
||||
if (unattendedName.IsNullOrWhiteSpace()
|
||||
|| unattendedEmail.IsNullOrWhiteSpace()
|
||||
|| unattendedPassword.IsNullOrWhiteSpace())
|
||||
{
|
||||
return;
|
||||
}
|
||||
var unattendedName = _globalSettings.UnattendedUserName;
|
||||
var unattendedEmail = _globalSettings.UnattendedUserEmail;
|
||||
var unattendedPassword = _globalSettings.UnattendedUserPassword;
|
||||
|
||||
var admin = _userService.GetUserById(Core.Constants.Security.SuperUserId);
|
||||
if (admin == null)
|
||||
{
|
||||
throw new InvalidOperationException("Could not find the super user!");
|
||||
}
|
||||
// Missing configuration values (json, env variables etc)
|
||||
if (unattendedName.IsNullOrWhiteSpace()
|
||||
|| unattendedEmail.IsNullOrWhiteSpace()
|
||||
|| unattendedPassword.IsNullOrWhiteSpace())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// User email/login has already been modified
|
||||
if (admin.Email == unattendedEmail)
|
||||
return;
|
||||
IUser admin = _userService.GetUserById(Core.Constants.Security.SuperUserId);
|
||||
if (admin == null)
|
||||
{
|
||||
throw new InvalidOperationException("Could not find the super user!");
|
||||
}
|
||||
|
||||
// Update name, email & login & save user
|
||||
admin.Name = unattendedName.Trim();
|
||||
admin.Email = unattendedEmail.Trim();
|
||||
admin.Username = unattendedEmail.Trim();
|
||||
_userService.Save(admin);
|
||||
// User email/login has already been modified
|
||||
if (admin.Email == unattendedEmail)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Change Password for the default user we ship out of the box
|
||||
// Uses same approach as NewInstall Step
|
||||
// Update name, email & login & save user
|
||||
admin.Name = unattendedName.Trim();
|
||||
admin.Email = unattendedEmail.Trim();
|
||||
admin.Username = unattendedEmail.Trim();
|
||||
_userService.Save(admin);
|
||||
|
||||
// TODO: usermanager why you no inject?!
|
||||
// Change Password for the default user we ship out of the box
|
||||
// Uses same approach as NewInstall Step
|
||||
|
||||
//var membershipUser = await _userManager.FindByIdAsync(Core.Constants.Security.SuperUserId.ToString());
|
||||
//if (membershipUser == null)
|
||||
//{
|
||||
// throw new InvalidOperationException($"No user found in membership provider with id of {Core.Constants.Security.SuperUserId}.");
|
||||
//}
|
||||
// TODO: usermanager why you no inject?!
|
||||
using IServiceScope scope = _serviceScopeFactory.CreateScope();
|
||||
IBackOfficeUserManager backOfficeUserManager = scope.ServiceProvider.GetRequiredService<IBackOfficeUserManager>();
|
||||
BackOfficeIdentityUser membershipUser = await backOfficeUserManager.FindByIdAsync(Core.Constants.Security.SuperUserId.ToString());
|
||||
if (membershipUser == null)
|
||||
{
|
||||
throw new InvalidOperationException($"No user found in membership provider with id of {Core.Constants.Security.SuperUserId}.");
|
||||
}
|
||||
|
||||
////To change the password here we actually need to reset it since we don't have an old one to use to change
|
||||
//var resetToken = await _userManager.GeneratePasswordResetTokenAsync(membershipUser);
|
||||
//if (string.IsNullOrWhiteSpace(resetToken))
|
||||
// throw new InvalidOperationException("Could not reset password: unable to generate internal reset token");
|
||||
//To change the password here we actually need to reset it since we don't have an old one to use to change
|
||||
var resetToken = await backOfficeUserManager.GeneratePasswordResetTokenAsync(membershipUser);
|
||||
if (string.IsNullOrWhiteSpace(resetToken))
|
||||
{
|
||||
throw new InvalidOperationException("Could not reset password: unable to generate internal reset token");
|
||||
}
|
||||
|
||||
//var resetResult = await _userManager.ChangePasswordWithResetAsync(membershipUser.Id, resetToken, unattendedPassword.Trim());
|
||||
//if (!resetResult.Succeeded)
|
||||
// throw new InvalidOperationException("Could not reset password: " + string.Join(", ", resetResult.Errors.ToErrorMessage()));
|
||||
IdentityResult resetResult = await backOfficeUserManager.ChangePasswordWithResetAsync(membershipUser.Id, resetToken, unattendedPassword.Trim());
|
||||
if (!resetResult.Succeeded)
|
||||
{
|
||||
throw new InvalidOperationException("Could not reset password: " + string.Join(", ", resetResult.Errors.ToErrorMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user