seed super-admin

This commit is contained in:
beo3000 2025-12-21 14:58:46 +01:00
parent db0a4b7c00
commit b8e18a52b3
3 changed files with 152 additions and 1 deletions

View File

@ -0,0 +1,137 @@
using Koogle.Domain.Entities;
using Koogle.Infrastructure.Identity;
using KoogleApp.Data;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
namespace Koogle.Infrastructure.Security;
public static class BootstrapSeeder
{
public static async Task SeedAsync(IServiceProvider services, IConfiguration config, IHostEnvironment env)
{
// Nur in Dev automatisch Prod nur mit explizitem Flag
var allowSeed = env.IsDevelopment() || config.GetValue<bool>("Bootstrap:EnableSeeding");
if (!allowSeed) return;
using var scope = services.CreateScope();
var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<ApplicationRole>>();
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
var appDb = scope.ServiceProvider.GetRequiredService<AppDbContext>();
// 1) Rollen
var roles = new[] { "SuperAdmin", "Admin", "Editor", "Viewer" };
foreach (var r in roles)
{
if (!await roleManager.RoleExistsAsync(r))
await roleManager.CreateAsync(new ApplicationRole { Name = r });
}
// 2) SuperAdmin User (Identity)
var adminEmail = config["Bootstrap:SuperAdmin:Email"];
var adminUserName = config["Bootstrap:SuperAdmin:UserName"] ?? adminEmail;
var adminPassword = config["Bootstrap:SuperAdmin:Password"];
if (string.IsNullOrWhiteSpace(adminEmail) || string.IsNullOrWhiteSpace(adminPassword))
throw new InvalidOperationException("Bootstrap SuperAdmin credentials missing. Set Bootstrap:SuperAdmin:Email and :Password.");
var adminUser = await userManager.FindByEmailAsync(adminEmail);
if (adminUser == null)
{
adminUser = new ApplicationUser
{
UserName = adminUserName,
Email = adminEmail,
EmailConfirmed = env.IsDevelopment() // Dev: praktisch, Prod: lieber false + Confirm Flow
};
var createResult = await userManager.CreateAsync(adminUser, adminPassword);
if (!createResult.Succeeded)
throw new InvalidOperationException("Failed to create SuperAdmin: " +
string.Join("; ", createResult.Errors.Select(e => $"{e.Code}:{e.Description}")));
}
// 3) Rolle zuweisen
if (!await userManager.IsInRoleAsync(adminUser, "SuperAdmin"))
await userManager.AddToRoleAsync(adminUser, "SuperAdmin");
// 4) Domain UserProfile anlegen
var profile = await appDb.UserProfiles.SingleOrDefaultAsync(p => p.IdentityUserId == adminUser.Id);
if (profile == null)
{
profile = new UserProfile
{
IdentityUserId = adminUser.Id,
DisplayName = "Super Admin",
Locale = "de-DE",
TimeZone = "Europe/Berlin",
CreatedAt = DateTime.UtcNow
};
appDb.UserProfiles.Add(profile);
await appDb.SaveChangesAsync();
}
// Optional: Default-Club erstellen + Membership + RoleAssignments (nur wenn gewünscht)
if (config.GetValue<bool>("Bootstrap:CreateDefaultClub"))
{
var clubName = config["Bootstrap:DefaultClub:Name"] ?? "Default Club";
var club = await appDb.Clubs.FirstOrDefaultAsync(c => c.Name == clubName);
if (club == null)
{
club = new Club { Name = clubName, CreatedAt = DateTime.UtcNow };
appDb.Clubs.Add(club);
await appDb.SaveChangesAsync();
}
// Membership (UserProfileClub) wenn du das nutzt
var membership = await appDb.UserProfileClubs
.FindAsync(profile.Id, club.Id);
if (membership == null)
{
membership = new UserProfileClub
{
UserProfileId = profile.Id,
ClubId = club.Id,
IsDefault = true,
AssignedAt = DateTime.UtcNow,
AssignedById = adminUser.Id
};
appDb.UserProfileClubs.Add(membership);
await appDb.SaveChangesAsync();
}
// Club-Rollen assignments (B2): Admin/Editor/Viewer o.ä.
// Hier: Admin im Default-Club
var roleExists = await appDb.UserProfileClubRoleAssignments.AnyAsync(a =>
a.UserProfileId == profile.Id && a.ClubId == club.Id && a.RoleName == "Admin" && !a.IsDeleted);
if (!roleExists)
{
appDb.UserProfileClubRoleAssignments.Add(new UserProfileClubRoleAssignment
{
UserProfileId = profile.Id,
ClubId = club.Id,
RoleId = Guid.Empty, // optional, wenn du RoleId nicht zwingend brauchst
RoleName = "Admin",
AssignedAt = DateTime.UtcNow,
AssignedById = adminUser.Id,
CreatedAt = DateTime.UtcNow
});
await appDb.SaveChangesAsync();
}
}
}
}

View File

@ -51,7 +51,7 @@ using (var scope = app.Services.CreateScope())
{
await IdentityRoleSeeder.SeedAsync(scope.ServiceProvider);
}
await BootstrapSeeder.SeedAsync(app.Services, app.Configuration, app.Environment);

View File

@ -1,4 +1,18 @@
{
"Bootstrap": {
"EnableSeeding": true,
"CreateDefaultClub": true,
"SuperAdmin": {
"Email": "ch@koogle.de",
"UserName": "ch@koogle.de",
"Password": "DEV_only3000!"
},
"DefaultClub": {
"Name": "Koogle Demo Club"
}
},
"Logging": {
"LogLevel": {
"Default": "Information",