using System; using System.Linq; using System.Security.Cryptography; using System.Threading.Tasks; using dotenv.net; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using PhoenixLib.Extensions; using PhoenixLib.Logging; using Plugin.Database; using Plugin.Database.DB; using Plugin.Database.Entities.Account; using Toolkit.Commands; using WingsAPI.Plugins; using WingsAPI.Plugins.Exceptions; using WingsEmu.DTOs.Account; namespace Toolkit.CommandHandlers; public class CreateAccountCommandHandler { private static ServiceProvider BuildCoreContainer(CreateAccountCommand command) { DotEnv.Load(new DotEnvOptions(true, new[] { command.EnvFile })); var pluginBuilder = new ServiceCollection(); pluginBuilder.AddTransient(); ServiceProvider container = pluginBuilder.BuildServiceProvider(); var coreBuilder = new ServiceCollection(); foreach (IDependencyInjectorPlugin plugin in container.GetServices()) { try { Log.Debug($"[PLUGIN_LOADER] Loading generic plugin {plugin.Name}..."); plugin.AddDependencies(coreBuilder); } catch (PluginException e) { Log.Error("[PLUGIN_LOADER] Add dependencies", e); } } coreBuilder.AddLogging(builder => { builder.ClearProviders(); builder.AddConsole(); builder.AddFilter("Microsoft", LogLevel.Warning); builder.AddFilter("Microsoft.EntityFrameworkCore.Database.Command", LogLevel.Warning); }); return coreBuilder.BuildServiceProvider(); } public static async Task HandleAsync(CreateAccountCommand command) { await using ServiceProvider coreContainer = BuildCoreContainer(command); try { IDbContextFactory factory = coreContainer.GetRequiredService>(); await using GameContext context = factory.CreateDbContext(); await context.Database.MigrateAsync(); if (context.Account.Any()) { Log.Info("[DEFAULT_ACCOUNT] Accounts were already present!"); return 0; } string adminUsername = Environment.GetEnvironmentVariable("TOOLKIT_ADMIN_USERNAME") ?? "admin"; string adminPassword = Environment.GetEnvironmentVariable("TOOLKIT_ADMIN_PASSWORD"); if (string.IsNullOrWhiteSpace(adminPassword)) { byte[] generatedPasswordBytes = new byte[24]; RandomNumberGenerator.Fill(generatedPasswordBytes); adminPassword = Convert.ToBase64String(generatedPasswordBytes); Log.Warn($"[DEFAULT ACCOUNT] TOOLKIT_ADMIN_PASSWORD is missing. Generated temporary password for '{adminUsername}': {adminPassword}"); } context.Account.Add(new AccountEntity { Authority = AuthorityType.Root, Language = AccountLanguage.EN, Name = adminUsername, Password = adminPassword.ToSha512() }); await context.SaveChangesAsync(); Log.Info("[DEFAULT_ACCOUNT] Accounts created!"); return 0; } catch (Exception e) { Log.Error("[DEFAULT_ACCOUNT] Error", e); return 1; } } }