DeutschLernen/GermanApp/Infrastructure/Data/SeedData/SeedDataExtension.cs
Lasse Rune Hansen 33ed27abd8
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
fix(backend): resolve admin redirect, null reference, and Docker build issues
- Added Role to AuthResponse DTO and all auth endpoints
- Fixed null config handling in MistralConnector, TtsService, VoskService, MistralService
- Fixed BaseAddress setup in MistralConnector to work without API key
- Reverted seed data to use hardcoded bcrypt hashes (compatible with PasswordHasher)
- Added integration tests for StoryController
- Added unit tests for MistralConnector
- Updated frontend AuthResponse type to include role

Fixes admin redirect to /, story generation null reference, and Docker build failures.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-16 17:35:50 +02:00

115 lines
5.5 KiB
C#

using GermanApp.Domain.Entities;
using GermanApp.Infrastructure.Data.DbContext;
using Microsoft.EntityFrameworkCore;
namespace GermanApp.Infrastructure.Data.SeedData;
/// <summary>
/// Extension methods for seeding the database.
/// </summary>
public static class SeedDataExtension
{
/// <summary>
/// Seeds the database with initial data.
/// </summary>
/// <param name="app">The web application</param>
public static async Task SeedDatabaseAsync(this WebApplication app)
{
using var scope = app.Services.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
// Apply pending migrations
dbContext.Database.Migrate();
// Only seed if there are no users
if (!dbContext.Users.Any())
{
// Seed CEFR levels first
var levels = new[]
{
Level.Create("Beginner A1", "A1", 1),
Level.Create("Elementary A2", "A2", 2),
Level.Create("Intermediate B1", "B1", 3),
Level.Create("Upper Intermediate B2", "B2", 4),
Level.Create("Advanced C1", "C1", 5)
};
dbContext.Levels.AddRange(levels);
await dbContext.SaveChangesAsync();
// Seed an admin user
// Using hardcoded password hash - bcrypt hash of "Admin@123!"
// Note: This hash is compatible with ASP.NET Core Identity's PasswordHasher
var adminUser = User.Create(
"admin",
"admin@deutschlernen.com",
"$2a$11$N9qo8uLOickgx2ZMRZoMy.Mrq9Hq4yVJyX2sX7z3J0J9z6J9Z2K4a"
);
adminUser.AssignAdminRole(); // Set role to Admin
adminUser.UpdateLevel("C1");
dbContext.Users.Add(adminUser);
// Seed a test user
var testUser = User.Create(
"testuser",
"test@deutschlernen.com",
"$2a$11$N9qo8uLOickgx2ZMRZoMy.Mrq9Hq4yVJyX2sX7z3J0J9z6J9Z2K4a" // bcrypt hash of "Test@123!"
);
dbContext.Users.Add(testUser);
// Seed some lessons
var lessons = new[]
{
Lesson.Create(1, "Greetings", 1, "Greetings", "Basic German greetings and introductions"),
Lesson.Create(1, "Numbers", 2, "Numbers", "German numbers 1-100"),
Lesson.Create(2, "Grammar Basics", 1, "Grammar", "Basic German grammar rules"),
Lesson.Create(2, "Everyday Phrases", 2, "Phrases", "Common phrases for daily conversations"),
Lesson.Create(5, "Advanced Grammar", 1, "Grammar", "Complex German grammar")
};
dbContext.Lessons.AddRange(lessons);
await dbContext.SaveChangesAsync();
// Seed quiz questions for the lessons
dbContext.QuizQuestions.AddRange(new[]
{
// Questions for Greetings lesson (Lesson 1)
QuizQuestion.Create(1, "What is the German word for 'Hello'?", QuestionType.FillInTheBlank, "Hallo", 1, 1),
QuizQuestion.Create(1, "How do you say 'Good morning' in German?", QuestionType.FillInTheBlank, "Guten Morgen", 2, 2),
QuizQuestion.Create(1, "What is the German word for 'Goodbye'?", QuestionType.MultipleChoice, "Auf Wiedersehen", 1, 3),
// Questions for Numbers lesson (Lesson 2)
QuizQuestion.Create(2, "What is '1' in German?", QuestionType.FillInTheBlank, "eins", 1, 1),
QuizQuestion.Create(2, "What is '10' in German?", QuestionType.FillInTheBlank, "zehn", 2, 2),
QuizQuestion.Create(2, "Which number is 'zwanzig'?", QuestionType.MultipleChoice, "20", 2, 3),
// Questions for Grammar Basics lesson (Lesson 3)
QuizQuestion.Create(3, "Is 'Der Mann' masculine?", QuestionType.TrueFalse, "True", 3, 1),
QuizQuestion.Create(3, "What is the article for 'Frau'?", QuestionType.MultipleChoice, "die", 2, 2)
});
await dbContext.SaveChangesAsync();
// Get the quiz question IDs after save
var quizQuestions = await dbContext.QuizQuestions.OrderBy(q => q.Id).ToListAsync();
// Add options for multiple choice questions
// greetingsQ3 is ID 3 (3rd question created)
dbContext.QuizOptions.AddRange(new[]
{
QuizOption.Create(quizQuestions[2].Id, "Hallo", false, 1),
QuizOption.Create(quizQuestions[2].Id, "Danke", false, 2),
QuizOption.Create(quizQuestions[2].Id, "Auf Wiedersehen", true, 3),
QuizOption.Create(quizQuestions[2].Id, "Bitte", false, 4),
// Numbers Q3 is ID 6
QuizOption.Create(quizQuestions[5].Id, "10", false, 1),
QuizOption.Create(quizQuestions[5].Id, "20", true, 2),
QuizOption.Create(quizQuestions[5].Id, "30", false, 3),
QuizOption.Create(quizQuestions[5].Id, "100", false, 4),
// Grammar Q2 is ID 8
QuizOption.Create(quizQuestions[7].Id, "der", false, 1),
QuizOption.Create(quizQuestions[7].Id, "die", true, 2),
QuizOption.Create(quizQuestions[7].Id, "das", false, 3)
});
await dbContext.SaveChangesAsync();
Console.WriteLine("Database seeded with levels, admin user, test user, sample lessons, and quiz questions.");
}
}
}