feat(admincli): add command for creating a user
This commit is contained in:
@@ -11,5 +11,6 @@
|
||||
</PackageVersion>
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.2" />
|
||||
<PackageVersion Include="Spectre.Console" Version="0.54.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,3 +1,4 @@
|
||||
[*.cs]
|
||||
|
||||
dotnet_diagnostic.CA1303.severity = none
|
||||
dotnet_diagnostic.CA2007.severity = none
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
namespace FiscalOS.AdminCLI;
|
||||
|
||||
internal sealed class App(
|
||||
IAnsiConsole console,
|
||||
IPasswordHasher passwordHasher,
|
||||
IServiceScopeFactory serviceScopeFactory
|
||||
) : IHostedService
|
||||
{
|
||||
private readonly IAnsiConsole _console = console;
|
||||
private readonly IServiceScopeFactory _serviceScopeFactory = serviceScopeFactory;
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
var config = scope.ServiceProvider.GetRequiredService<IConfiguration>();
|
||||
var appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
|
||||
var selectionPrompt = new SelectionPrompt<string>()
|
||||
.Title("What do you want to do?")
|
||||
.AddChoices(Commands.All);
|
||||
|
||||
var command = await _console.PromptAsync(selectionPrompt, cancellationToken);
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case Commands.CreateUser:
|
||||
var username = await _console.AskAsync<string>("Enter the [green]username[/]:", cancellationToken);
|
||||
var password = _console.Prompt(
|
||||
new TextPrompt<string>("Enter the [green]password[/]:")
|
||||
.PromptStyle("red")
|
||||
.Secret()
|
||||
);
|
||||
|
||||
var hashedPassword = passwordHasher.Hash(password);
|
||||
var user = User.From(username, hashedPassword);
|
||||
|
||||
await appDbContext.Users.AddAsync(user, cancellationToken);
|
||||
await appDbContext.SaveChangesAsync(cancellationToken);
|
||||
|
||||
_console.MarkupLine($"User [green]{username}[/] created successfully.");
|
||||
break;
|
||||
case Commands.Exit:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace FiscalOS.AdminCLI;
|
||||
|
||||
internal static class Commands
|
||||
{
|
||||
public const string CreateUser = "Create User";
|
||||
public const string Exit = "Exit";
|
||||
|
||||
public static readonly string[] All = [CreateUser, Exit];
|
||||
}
|
||||
@@ -4,4 +4,20 @@
|
||||
<OutputType>Exe</OutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" />
|
||||
<PackageReference Include="Spectre.Console" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="appsettings*.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\FiscalOS.Infra\FiscalOS.Infra.csproj" />
|
||||
<ProjectReference Include="..\FiscalOS.Core\FiscalOS.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
// TODO: We need a way to add
|
||||
// a user to the system with
|
||||
// a properly hashed password
|
||||
// so need something like this:
|
||||
//
|
||||
// 1. Ask for username
|
||||
// 2. Ask for user password
|
||||
// 3. Hash user password
|
||||
// 4. Save user to database
|
||||
|
||||
Console.WriteLine("Hello, World!");
|
||||
await Host.CreateDefaultBuilder(args)
|
||||
.ConfigureAppConfiguration(
|
||||
static c => c.SetBasePath(AppContext.BaseDirectory)
|
||||
.AddJsonFile("appsettings.json")
|
||||
.AddEnvironmentVariables()
|
||||
)
|
||||
.ConfigureLogging(static c => c.ClearProviders())
|
||||
.ConfigureServices(static (_, services) =>
|
||||
{
|
||||
services.AddSingleton(AnsiConsole.Console);
|
||||
services.AddInfrastructure();
|
||||
services.AddHostedService<App>();
|
||||
})
|
||||
.Build()
|
||||
.StartAsync();
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
global using FiscalOS.AdminCLI;
|
||||
global using FiscalOS.Core.Authentication;
|
||||
global using FiscalOS.Core.Identity;
|
||||
global using FiscalOS.Infra.Data;
|
||||
global using FiscalOS.Infra.DependencyInjection;
|
||||
|
||||
global using Microsoft.Extensions.Configuration;
|
||||
global using Microsoft.Extensions.DependencyInjection;
|
||||
global using Microsoft.Extensions.Hosting;
|
||||
global using Microsoft.Extensions.Logging;
|
||||
|
||||
global using Spectre.Console;
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"AppDbContextOptions": {
|
||||
"DatabaseFilePath": "DatabaseFilePath"
|
||||
}
|
||||
}
|
||||
@@ -51,9 +51,7 @@ public sealed class AppDbContext(IOptions<AppDbContextOptions> ctxOptions) : DbC
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
eb.Property(static u => u.Username);
|
||||
eb.Property(static u => u.HashedPassword);
|
||||
});
|
||||
|
||||
eb.Property(static u => u.HashedPassword); });
|
||||
modelBuilder.Entity<RefreshToken>(static eb =>
|
||||
{
|
||||
eb.Property(static t => t.Id);
|
||||
|
||||
@@ -3,6 +3,7 @@ namespace FiscalOS.Infra.Data;
|
||||
public sealed record AppDbContextOptions
|
||||
{
|
||||
public string DatabaseFilePath { get; init; } = string.Empty;
|
||||
|
||||
public string GetFullyQualifiedDatabasePath()
|
||||
{
|
||||
return Path.GetFullPath(DatabaseFilePath, AppContext.BaseDirectory);
|
||||
|
||||
@@ -5,6 +5,7 @@ public static class ServiceCollectionExtensions
|
||||
public static IServiceCollection AddInfrastructure(this IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton(TimeProvider.System);
|
||||
services.ConfigureOptions<JwtOptionsSetup>();
|
||||
services.AddSingleton<ITokenGenerator, TokenGenerator>(TokenGenerator.From);
|
||||
services.AddSingleton<IPasswordHasher, PasswordHasher>(PasswordHasher.From);
|
||||
services.ConfigureOptions<AppDbContextOptionsSetup>();
|
||||
|
||||
Reference in New Issue
Block a user