diff --git a/src/Core/Database/Database.Core/scripts/03-crud/01-UserAccount/USP_CreateUserAccount.sql b/src/Core/Database/Database.Core/scripts/03-crud/01-UserAccount/USP_CreateUserAccount.sql
index a99b12d..80f71d5 100644
--- a/src/Core/Database/Database.Core/scripts/03-crud/01-UserAccount/USP_CreateUserAccount.sql
+++ b/src/Core/Database/Database.Core/scripts/03-crud/01-UserAccount/USP_CreateUserAccount.sql
@@ -12,6 +12,8 @@ AS
BEGIN
SET NOCOUNT ON;
+ DECLARE @Inserted TABLE (UserAccountID UNIQUEIDENTIFIER);
+
INSERT INTO UserAccount
(
Username,
@@ -20,6 +22,7 @@ BEGIN
DateOfBirth,
Email
)
+ OUTPUT INSERTED.UserAccountID INTO @Inserted
VALUES
(
@Username,
@@ -29,5 +32,5 @@ BEGIN
@Email
);
- SELECT @UserAccountId AS UserAccountId;
+ SELECT @UserAccountId = UserAccountID FROM @Inserted;
END;
diff --git a/src/Core/Database/Database.Core/scripts/03-crud/02-Auth/USP_RegisterUser.sql b/src/Core/Database/Database.Core/scripts/03-crud/02-Auth/USP_RegisterUser.sql
index 8f10b83..a784788 100644
--- a/src/Core/Database/Database.Core/scripts/03-crud/02-Auth/USP_RegisterUser.sql
+++ b/src/Core/Database/Database.Core/scripts/03-crud/02-Auth/USP_RegisterUser.sql
@@ -27,10 +27,9 @@ BEGIN
THROW 50000, 'Failed to create user account.', 1;
END
-
- EXEC dbo.usp_RotateUserCredential
- @UserAccountId = @UserAccountId_,
- @Hash = @Hash;
+ INSERT INTO dbo.UserCredential
+ (UserAccountId, Hash)
+ VALUES (@UserAccountId_, @Hash);
IF @@ROWCOUNT = 0
BEGIN
diff --git a/src/Core/Database/Database.Seed/Database.Seed.csproj b/src/Core/Database/Database.Seed/Database.Seed.csproj
index 70839e4..e9b8521 100644
--- a/src/Core/Database/Database.Seed/Database.Seed.csproj
+++ b/src/Core/Database/Database.Seed/Database.Seed.csproj
@@ -14,9 +14,11 @@
Version="1.3.1"
/>
+
+
diff --git a/src/Core/Database/Database.Seed/Program.cs b/src/Core/Database/Database.Seed/Program.cs
index 39640cd..8612f2e 100644
--- a/src/Core/Database/Database.Seed/Program.cs
+++ b/src/Core/Database/Database.Seed/Program.cs
@@ -1,5 +1,7 @@
using DBSeed;
using Microsoft.Data.SqlClient;
+using DbUp;
+using System.Reflection;
try
{
@@ -14,8 +16,47 @@ try
await using var connection = new SqlConnection(connectionString);
await connection.OpenAsync();
+ // drop and recreate the database
+ var useMaster = connection.CreateCommand();
+ useMaster.CommandText = "USE master;";
+ await useMaster.ExecuteNonQueryAsync();
+
+ var dbName = "Biergarten";
+ var dropDb = connection.CreateCommand();
+ dropDb.CommandText = $@"
+ IF DB_ID(N'{dbName}') IS NOT NULL
+ BEGIN
+ ALTER DATABASE [{dbName}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
+ DROP DATABASE [{dbName}];
+ END";
+ await dropDb.ExecuteNonQueryAsync();
+
+ var createDb = connection.CreateCommand();
+ createDb.CommandText = $@"CREATE DATABASE [{dbName}];";
+ await createDb.ExecuteNonQueryAsync();
+ await connection.CloseAsync();
+ await connection.OpenAsync();
+
+
Console.WriteLine("Connected to database.");
+ Console.WriteLine("Starting migrations...");
+
+ // Run Database.Core migrations (embedded resources) via DbUp
+ var migrationAssembly = Assembly.Load("Database.Core");
+ var upgrader = DeployChanges
+ .To.SqlDatabase(connectionString)
+ .WithScriptsEmbeddedInAssembly(migrationAssembly)
+ .LogToConsole()
+ .Build();
+
+ var upgradeResult = upgrader.PerformUpgrade();
+ if (!upgradeResult.Successful)
+ throw upgradeResult.Error;
+
+ Console.WriteLine("Migrations completed.");
+
+
ISeeder[] seeders =
[
new LocationSeeder(),
@@ -30,6 +71,7 @@ try
}
Console.WriteLine("Seed completed successfully.");
+ await connection.CloseAsync();
return 0;
}
catch (Exception ex)
diff --git a/src/Core/Database/Database.Seed/UserSeeder.cs b/src/Core/Database/Database.Seed/UserSeeder.cs
index 6efdfc3..437ad46 100644
--- a/src/Core/Database/Database.Seed/UserSeeder.cs
+++ b/src/Core/Database/Database.Seed/UserSeeder.cs
@@ -9,11 +9,8 @@ using Microsoft.Data.SqlClient;
namespace DBSeed
{
-
internal class UserSeeder : ISeeder
{
-
-
private static readonly IReadOnlyList<(
string FirstName,
string LastName
@@ -129,36 +126,38 @@ namespace DBSeed
int createdCredentials = 0;
int createdVerifications = 0;
+
foreach (var (firstName, lastName) in SeedNames)
{
- // create the user in the database
- var userAccountId = Guid.NewGuid();
- await AddUserAccountAsync(connection, new UserAccount
- {
- UserAccountId = userAccountId,
- FirstName = firstName,
- LastName = lastName,
- Email = $"{firstName}.{lastName}@thebiergarten.app",
- Username = $"{firstName[0]}.{lastName}",
- DateOfBirth = GenerateDateOfBirth(rng)
- });
- createdUsers++;
+ // prepare user fields
+ var username = $"{firstName[0]}.{lastName}";
+ var email = $"{firstName}.{lastName}@thebiergarten.app";
+ var dob = GenerateDateOfBirth(rng);
- // add user credentials
- if (!await HasUserCredentialAsync(connection, userAccountId))
- {
- string pwd = generator.Generate(
- length: 64,
- numberOfDigits: 10,
- numberOfSymbols: 10
- );
- string hash = GeneratePasswordHash(pwd);
- await AddUserCredentialAsync(connection, userAccountId, hash);
- createdCredentials++;
- }
+ // generate a password and hash it
+ string pwd = generator.Generate(
+ length: 64,
+ numberOfDigits: 10,
+ numberOfSymbols: 10
+ );
+ string hash = GeneratePasswordHash(pwd);
+
+ // register the user (creates account + credential)
+ var userAccountId = await RegisterUserAsync(
+ connection,
+ username,
+ firstName,
+ lastName,
+ dob,
+ email,
+ hash
+ );
+ createdUsers++;
+ createdCredentials++;
// add user verification
if (await HasUserVerificationAsync(connection, userAccountId)) continue;
+
await AddUserVerificationAsync(connection, userAccountId);
createdVerifications++;
}
@@ -168,19 +167,34 @@ namespace DBSeed
Console.WriteLine($"Added {createdVerifications} user verifications.");
}
- private static async Task AddUserAccountAsync(SqlConnection connection, UserAccount ua)
+ private static async Task RegisterUserAsync(
+ SqlConnection connection,
+ string username,
+ string firstName,
+ string lastName,
+ DateTime dateOfBirth,
+ string email,
+ string hash
+ )
{
- await using var command = new SqlCommand("usp_CreateUserAccount", connection);
+ await using var command = new SqlCommand("dbo.USP_RegisterUser", connection);
command.CommandType = CommandType.StoredProcedure;
- command.Parameters.Add("@UserAccountId", SqlDbType.UniqueIdentifier).Value = ua.UserAccountId;
- command.Parameters.Add("@Username", SqlDbType.NVarChar, 100).Value = ua.Username;
- command.Parameters.Add("@FirstName", SqlDbType.NVarChar, 100).Value = ua.FirstName;
- command.Parameters.Add("@LastName", SqlDbType.NVarChar, 100).Value = ua.LastName;
- command.Parameters.Add("@Email", SqlDbType.NVarChar, 256).Value = ua.Email;
- command.Parameters.Add("@DateOfBirth", SqlDbType.Date).Value = ua.DateOfBirth;
+ var idParam = new SqlParameter("@UserAccountId_", SqlDbType.UniqueIdentifier)
+ {
+ Direction = ParameterDirection.Output
+ };
+ command.Parameters.Add(idParam);
+
+ command.Parameters.Add("@Username", SqlDbType.VarChar, 64).Value = username;
+ command.Parameters.Add("@FirstName", SqlDbType.NVarChar, 128).Value = firstName;
+ command.Parameters.Add("@LastName", SqlDbType.NVarChar, 128).Value = lastName;
+ command.Parameters.Add("@DateOfBirth", SqlDbType.DateTime).Value = dateOfBirth;
+ command.Parameters.Add("@Email", SqlDbType.VarChar, 128).Value = email;
+ command.Parameters.Add("@Hash", SqlDbType.NVarChar, -1).Value = hash;
await command.ExecuteNonQueryAsync();
+ return (Guid)idParam.Value;
}
private static string GeneratePasswordHash(string pwd)
@@ -199,39 +213,6 @@ namespace DBSeed
return $"{Convert.ToBase64String(salt)}:{Convert.ToBase64String(hash)}";
}
- private static async Task HasUserCredentialAsync(
- SqlConnection connection,
- Guid userAccountId
- )
- {
- const string sql = $"""
- SELECT 1
- FROM dbo.UserCredential
- WHERE UserAccountId = @UserAccountId;
- """;
- await using var command = new SqlCommand(sql, connection);
- command.Parameters.AddWithValue("@UserAccountId", userAccountId);
- object? result = await command.ExecuteScalarAsync();
- return result is not null;
- }
-
- private static async Task AddUserCredentialAsync(
- SqlConnection connection,
- Guid userAccountId,
- string hash
- )
- {
- await using var command = new SqlCommand(
- "dbo.USP_AddUserCredential",
- connection
- );
- command.CommandType = CommandType.StoredProcedure;
- command.Parameters.AddWithValue("@UserAccountId", userAccountId);
- command.Parameters.AddWithValue("@Hash", hash);
-
- await command.ExecuteNonQueryAsync();
- }
-
private static async Task HasUserVerificationAsync(
SqlConnection connection,
Guid userAccountId
@@ -258,11 +239,11 @@ namespace DBSeed
connection
);
command.CommandType = CommandType.StoredProcedure;
- command.Parameters.AddWithValue("@UserAccountID", userAccountId);
+ command.Parameters.AddWithValue("@UserAccountID_", userAccountId);
await command.ExecuteNonQueryAsync();
}
-
+
private static DateTime GenerateDateOfBirth(Random random)
{
int age = 19 + random.Next(0, 30);