Update stored procs/udf and update docker config

This commit is contained in:
Aaron Po
2025-11-13 10:18:03 +00:00
parent a200164609
commit b86607e37a
16 changed files with 991 additions and 337 deletions

263
DataLayer/seed/SeedDB.cs Normal file
View File

@@ -0,0 +1,263 @@
using System.Data;
using System.Security.Cryptography;
using System.Text;
using Konscious.Security.Cryptography;
using Microsoft.Data.SqlClient;
string ConnectionString = Environment.GetEnvironmentVariable(
"DB_CONNECTION_STRING"
)!;
static async Task BuildSchema(SqlConnection connection)
{
string sql = await File.ReadAllTextAsync(GetScriptPath("schema.sql"));
await ExecuteScriptAsync(connection, sql);
Console.WriteLine("Database schema created or updated successfully.");
}
static async Task AddStoredProcsAndFunctions(SqlConnection connection)
{
// New approach: load functions first, then procedures, from dedicated folders.
// Fallback to legacy combined file if folders are missing.
string projectRoot = Path.GetFullPath(
Path.Combine(AppContext.BaseDirectory, "..", "..", "..")
);
string functionsDir = Path.Combine(projectRoot, "seed", "functions");
string proceduresDir = Path.Combine(projectRoot, "seed", "procedures");
if (Directory.Exists(functionsDir))
{
foreach (
string file in Directory
.EnumerateFiles(
functionsDir,
"*.sql",
SearchOption.TopDirectoryOnly
)
.OrderBy(f => f, StringComparer.OrdinalIgnoreCase)
)
{
string sql = await File.ReadAllTextAsync(file);
await ExecuteScriptAsync(connection, sql);
Console.WriteLine(
$"Executed function script: {Path.GetFileName(file)}"
);
}
}
if (Directory.Exists(proceduresDir))
{
foreach (
string file in Directory
.EnumerateFiles(
proceduresDir,
"*.sql",
SearchOption.TopDirectoryOnly
)
.OrderBy(f => f, StringComparer.OrdinalIgnoreCase)
)
{
string sql = await File.ReadAllTextAsync(file);
await ExecuteScriptAsync(connection, sql);
Console.WriteLine(
$"Executed procedure script: {Path.GetFileName(file)}"
);
}
}
Console.WriteLine(
"Functions and stored procedures added or updated successfully."
);
return;
}
static async Task RunSeedAsync(SqlConnection connection)
{
await ExecuteStoredProcedureAsync(connection, "dbo.USP_AddTestUsers");
Console.WriteLine("Inserted or refreshed test users.");
DataTable credentialRows = await BuildCredentialTableAsync(connection);
if (credentialRows.Rows.Count > 0)
{
await ExecuteCredentialProcedureAsync(connection, credentialRows);
Console.WriteLine(
$"Generated {credentialRows.Rows.Count} credential hashes."
);
}
else
{
Console.WriteLine("No new credentials required.");
}
await ExecuteStoredProcedureAsync(
connection,
"dbo.USP_CreateUserVerification"
);
Console.WriteLine("Ensured verification rows exist for all users.");
}
static async Task ExecuteStoredProcedureAsync(
SqlConnection connection,
string storedProcedureName
)
{
await using SqlCommand command = new SqlCommand(
storedProcedureName,
connection
);
command.CommandType = CommandType.StoredProcedure;
await command.ExecuteNonQueryAsync();
}
static async Task ExecuteCredentialProcedureAsync(
SqlConnection connection,
DataTable credentialTable
)
{
await using SqlCommand command = new SqlCommand(
"dbo.USP_AddUserCredentials",
connection
);
command.CommandType = CommandType.StoredProcedure;
SqlParameter tvpParameter = command.Parameters.Add(
"@Hash",
SqlDbType.Structured
);
tvpParameter.TypeName = "dbo.TblUserHashes";
tvpParameter.Value = credentialTable;
await command.ExecuteNonQueryAsync();
}
static async Task<DataTable> BuildCredentialTableAsync(SqlConnection connection)
{
const string sql = """
SELECT ua.UserAccountID,
ua.Username
FROM dbo.UserAccount AS ua
WHERE NOT EXISTS (
SELECT 1
FROM dbo.UserCredential AS uc
WHERE uc.UserAccountID = ua.UserAccountID);
""";
await using SqlCommand command = new(sql, connection);
await using SqlDataReader reader = await command.ExecuteReaderAsync();
DataTable table = new();
table.Columns.Add("UserAccountId", typeof(Guid));
table.Columns.Add("Hash", typeof(string));
while (await reader.ReadAsync())
{
Guid userId = reader.GetGuid(0);
string username = reader.GetString(1);
string password = CreatePlainTextPassword(username);
string hash = GeneratePasswordHash(password);
DataRow row = table.NewRow();
row["UserAccountId"] = userId;
row["Hash"] = hash;
table.Rows.Add(row);
}
return table;
}
static string CreatePlainTextPassword(string username) => $"{username}#2025!";
static string GeneratePasswordHash(string password)
{
byte[] salt = RandomNumberGenerator.GetBytes(16);
var argon2 = new Argon2id(Encoding.UTF8.GetBytes(password))
{
Salt = salt,
DegreeOfParallelism = Math.Max(Environment.ProcessorCount, 1),
MemorySize = 65536,
Iterations = 4,
};
byte[] hash = argon2.GetBytes(32);
string saltBase64 = Convert.ToBase64String(salt);
string hashBase64 = Convert.ToBase64String(hash);
// Store salt and hash together so verification can rebuild the key material.
return $"{saltBase64}:{hashBase64}";
}
static async Task ExecuteScriptAsync(SqlConnection connection, string sql)
{
foreach (string batch in SplitSqlBatches(sql))
{
if (string.IsNullOrWhiteSpace(batch))
{
continue;
}
await using SqlCommand command = new(batch, connection);
await command.ExecuteNonQueryAsync();
}
}
static IEnumerable<string> SplitSqlBatches(string sql)
{
using StringReader reader = new(sql);
StringBuilder buffer = new();
string? line;
while ((line = reader.ReadLine()) is not null)
{
if (line.Trim().Equals("GO", StringComparison.OrdinalIgnoreCase))
{
yield return buffer.ToString();
buffer.Clear();
continue;
}
buffer.AppendLine(line);
}
if (buffer.Length > 0)
{
yield return buffer.ToString();
}
}
static string GetScriptPath(string fileName)
{
string projectRoot = Path.GetFullPath(
Path.Combine(AppContext.BaseDirectory, "..", "..", "..")
);
string candidate = Path.Combine(projectRoot, fileName);
if (File.Exists(candidate))
{
return candidate;
}
throw new FileNotFoundException(
$"SQL script '{fileName}' was not found.",
candidate
);
}
try
{
await using SqlConnection connection = new(ConnectionString);
await connection.OpenAsync();
Console.WriteLine("Connection to database established successfully.");
await BuildSchema(connection);
await AddStoredProcsAndFunctions(connection);
await RunSeedAsync(connection);
Console.WriteLine("Seeding complete.");
}
catch (Exception ex)
{
Console.Error.WriteLine($"Seeding failed: {ex.Message}");
Environment.ExitCode = 1;
}

View File

@@ -0,0 +1,19 @@
USE Biergarten;
GO
CREATE OR ALTER FUNCTION dbo.UDF_GetCountryIdByCode
(
@CountryCode NVARCHAR(2)
)
RETURNS UNIQUEIDENTIFIER
AS
BEGIN
DECLARE @CountryId UNIQUEIDENTIFIER;
SELECT @CountryId = CountryID
FROM dbo.Country
WHERE ISO3616_1 = @CountryCode;
RETURN @CountryId;
END;
GO

View File

@@ -0,0 +1,17 @@
USE Biergarten;
GO
CREATE OR ALTER FUNCTION dbo.UDF_GetStateProvinceIdByCode
(
@StateProvinceCode NVARCHAR(6)
)
RETURNS UNIQUEIDENTIFIER
AS
BEGIN
DECLARE @StateProvinceId UNIQUEIDENTIFIER;
SELECT @StateProvinceId = StateProvinceID
FROM dbo.StateProvince
WHERE ISO3616_2 = @StateProvinceCode;
RETURN @StateProvinceId;
END;
GO

View File

@@ -0,0 +1,504 @@
USE Biergarten;
GO
CREATE OR ALTER PROCEDURE dbo.USP_AddLocations
AS
BEGIN
SET NOCOUNT ON;
SET XACT_ABORT ON;
BEGIN TRANSACTION;
-- Countries (alpha-2)
WITH
Countries(CountryName, Alpha2)
AS
(
SELECT 'Canada', 'CA'
UNION ALL
SELECT 'Mexico', 'MX'
UNION ALL
SELECT 'United States', 'US'
)
INSERT INTO dbo.Country
(CountryName, ISO3616_1)
SELECT c.CountryName, c.Alpha2
FROM Countries AS c
WHERE NOT EXISTS (SELECT 1
FROM dbo.Country AS x
WHERE x.ISO3616_1 = c.Alpha2
);
WITH
Regions(StateProvinceName, ISO2, CountryAlpha2)
AS
(
-- United States (50 + DC + territories)
SELECT 'Alabama', 'US-AL', 'US'
UNION ALL
SELECT 'Alaska', 'US-AK', 'US'
UNION ALL
SELECT 'Arizona', 'US-AZ', 'US'
UNION ALL
SELECT 'Arkansas', 'US-AR', 'US'
UNION ALL
SELECT 'California', 'US-CA', 'US'
UNION ALL
SELECT 'Colorado', 'US-CO', 'US'
UNION ALL
SELECT 'Connecticut', 'US-CT', 'US'
UNION ALL
SELECT 'Delaware', 'US-DE', 'US'
UNION ALL
SELECT 'Florida', 'US-FL', 'US'
UNION ALL
SELECT 'Georgia', 'US-GA', 'US'
UNION ALL
SELECT 'Hawaii', 'US-HI', 'US'
UNION ALL
SELECT 'Idaho', 'US-ID', 'US'
UNION ALL
SELECT 'Illinois', 'US-IL', 'US'
UNION ALL
SELECT 'Indiana', 'US-IN', 'US'
UNION ALL
SELECT 'Iowa', 'US-IA', 'US'
UNION ALL
SELECT 'Kansas', 'US-KS', 'US'
UNION ALL
SELECT 'Kentucky', 'US-KY', 'US'
UNION ALL
SELECT 'Louisiana', 'US-LA', 'US'
UNION ALL
SELECT 'Maine', 'US-ME', 'US'
UNION ALL
SELECT 'Maryland', 'US-MD', 'US'
UNION ALL
SELECT 'Massachusetts', 'US-MA', 'US'
UNION ALL
SELECT 'Michigan', 'US-MI', 'US'
UNION ALL
SELECT 'Minnesota', 'US-MN', 'US'
UNION ALL
SELECT 'Mississippi', 'US-MS', 'US'
UNION ALL
SELECT 'Missouri', 'US-MO', 'US'
UNION ALL
SELECT 'Montana', 'US-MT', 'US'
UNION ALL
SELECT 'Nebraska', 'US-NE', 'US'
UNION ALL
SELECT 'Nevada', 'US-NV', 'US'
UNION ALL
SELECT 'New Hampshire', 'US-NH', 'US'
UNION ALL
SELECT 'New Jersey', 'US-NJ', 'US'
UNION ALL
SELECT 'New Mexico', 'US-NM', 'US'
UNION ALL
SELECT 'New York', 'US-NY', 'US'
UNION ALL
SELECT 'North Carolina', 'US-NC', 'US'
UNION ALL
SELECT 'North Dakota', 'US-ND', 'US'
UNION ALL
SELECT 'Ohio', 'US-OH', 'US'
UNION ALL
SELECT 'Oklahoma', 'US-OK', 'US'
UNION ALL
SELECT 'Oregon', 'US-OR', 'US'
UNION ALL
SELECT 'Pennsylvania', 'US-PA', 'US'
UNION ALL
SELECT 'Rhode Island', 'US-RI', 'US'
UNION ALL
SELECT 'South Carolina', 'US-SC', 'US'
UNION ALL
SELECT 'South Dakota', 'US-SD', 'US'
UNION ALL
SELECT 'Tennessee', 'US-TN', 'US'
UNION ALL
SELECT 'Texas', 'US-TX', 'US'
UNION ALL
SELECT 'Utah', 'US-UT', 'US'
UNION ALL
SELECT 'Vermont', 'US-VT', 'US'
UNION ALL
SELECT 'Virginia', 'US-VA', 'US'
UNION ALL
SELECT 'Washington', 'US-WA', 'US'
UNION ALL
SELECT 'West Virginia', 'US-WV', 'US'
UNION ALL
SELECT 'Wisconsin', 'US-WI', 'US'
UNION ALL
SELECT 'Wyoming', 'US-WY', 'US'
UNION ALL
SELECT 'District of Columbia', 'US-DC', 'US'
UNION ALL
SELECT 'Puerto Rico', 'US-PR', 'US'
UNION ALL
SELECT 'U.S. Virgin Islands', 'US-VI', 'US'
UNION ALL
SELECT 'Guam', 'US-GU', 'US'
UNION ALL
SELECT 'Northern Mariana Islands', 'US-MP', 'US'
UNION ALL
SELECT 'American Samoa', 'US-AS', 'US'
-- Canada (10 provinces + 3 territories)
UNION ALL
SELECT 'Ontario', 'CA-ON', 'CA'
UNION ALL
SELECT N'Québec', 'CA-QC', 'CA'
UNION ALL
SELECT 'Nova Scotia', 'CA-NS', 'CA'
UNION ALL
SELECT 'New Brunswick', 'CA-NB', 'CA'
UNION ALL
SELECT 'Manitoba', 'CA-MB', 'CA'
UNION ALL
SELECT 'British Columbia', 'CA-BC', 'CA'
UNION ALL
SELECT 'Prince Edward Island', 'CA-PE', 'CA'
UNION ALL
SELECT 'Saskatchewan', 'CA-SK', 'CA'
UNION ALL
SELECT 'Alberta', 'CA-AB', 'CA'
UNION ALL
SELECT 'Newfoundland and Labrador', 'CA-NL', 'CA'
UNION ALL
SELECT 'Northwest Territories', 'CA-NT', 'CA'
UNION ALL
SELECT 'Yukon', 'CA-YT', 'CA'
UNION ALL
SELECT 'Nunavut', 'CA-NU', 'CA'
-- Mexico (32 states incl. CDMX)
UNION ALL
SELECT 'Aguascalientes', 'MX-AGU', 'MX'
UNION ALL
SELECT 'Baja California', 'MX-BCN', 'MX'
UNION ALL
SELECT 'Baja California Sur', 'MX-BCS', 'MX'
UNION ALL
SELECT 'Campeche', 'MX-CAM', 'MX'
UNION ALL
SELECT 'Chiapas', 'MX-CHP', 'MX'
UNION ALL
SELECT 'Chihuahua', 'MX-CHH', 'MX'
UNION ALL
SELECT 'Coahuila de Zaragoza', 'MX-COA', 'MX'
UNION ALL
SELECT 'Colima', 'MX-COL', 'MX'
UNION ALL
SELECT 'Durango', 'MX-DUR', 'MX'
UNION ALL
SELECT 'Guanajuato', 'MX-GUA', 'MX'
UNION ALL
SELECT 'Guerrero', 'MX-GRO', 'MX'
UNION ALL
SELECT 'Hidalgo', 'MX-HID', 'MX'
UNION ALL
SELECT 'Jalisco', 'MX-JAL', 'MX'
UNION ALL
SELECT N'México State', 'MX-MEX', 'MX'
UNION ALL
SELECT N'Michoacán de Ocampo', 'MX-MIC', 'MX'
UNION ALL
SELECT 'Morelos', 'MX-MOR', 'MX'
UNION ALL
SELECT 'Nayarit', 'MX-NAY', 'MX'
UNION ALL
SELECT N'Nuevo León', 'MX-NLE', 'MX'
UNION ALL
SELECT 'Oaxaca', 'MX-OAX', 'MX'
UNION ALL
SELECT 'Puebla', 'MX-PUE', 'MX'
UNION ALL
SELECT N'Querétaro', 'MX-QUE', 'MX'
UNION ALL
SELECT 'Quintana Roo', 'MX-ROO', 'MX'
UNION ALL
SELECT N'San Luis Potosí', 'MX-SLP', 'MX'
UNION ALL
SELECT 'Sinaloa', 'MX-SIN', 'MX'
UNION ALL
SELECT 'Sonora', 'MX-SON', 'MX'
UNION ALL
SELECT 'Tabasco', 'MX-TAB', 'MX'
UNION ALL
SELECT 'Tamaulipas', 'MX-TAM', 'MX'
UNION ALL
SELECT 'Tlaxcala', 'MX-TLA', 'MX'
UNION ALL
SELECT 'Veracruz de Ignacio de la Llave', 'MX-VER', 'MX'
UNION ALL
SELECT N'Yucatán', 'MX-YUC', 'MX'
UNION ALL
SELECT 'Zacatecas', 'MX-ZAC', 'MX'
UNION ALL
SELECT N'Ciudad de México', 'MX-CMX', 'MX'
)
INSERT INTO dbo.StateProvince
(StateProvinceName, ISO3616_2, CountryID)
SELECT
r.StateProvinceName,
r.ISO2,
dbo.UDF_GetCountryIdByCode(r.CountryAlpha2)
FROM Regions AS r
WHERE NOT EXISTS (
SELECT 1
FROM dbo.StateProvince AS sp
WHERE sp.ISO3616_2 = r.ISO2
);
WITH
Cities(StateProvinceISO2, CityName)
AS
(
-- USA
SELECT 'US-CA', 'Los Angeles'
UNION ALL
SELECT 'US-CA', 'San Diego'
UNION ALL
SELECT 'US-CA', 'San Francisco'
UNION ALL
SELECT 'US-CA', 'Sacramento'
UNION ALL
SELECT 'US-TX', 'Houston'
UNION ALL
SELECT 'US-TX', 'Dallas'
UNION ALL
SELECT 'US-TX', 'Austin'
UNION ALL
SELECT 'US-TX', 'San Antonio'
UNION ALL
SELECT 'US-FL', 'Miami'
UNION ALL
SELECT 'US-FL', 'Orlando'
UNION ALL
SELECT 'US-FL', 'Tampa'
UNION ALL
SELECT 'US-NY', 'New York'
UNION ALL
SELECT 'US-NY', 'Buffalo'
UNION ALL
SELECT 'US-NY', 'Rochester'
UNION ALL
SELECT 'US-IL', 'Chicago'
UNION ALL
SELECT 'US-IL', 'Springfield'
UNION ALL
SELECT 'US-PA', 'Philadelphia'
UNION ALL
SELECT 'US-PA', 'Pittsburgh'
UNION ALL
SELECT 'US-AZ', 'Phoenix'
UNION ALL
SELECT 'US-AZ', 'Tucson'
UNION ALL
SELECT 'US-CO', 'Denver'
UNION ALL
SELECT 'US-CO', 'Colorado Springs'
UNION ALL
SELECT 'US-MA', 'Boston'
UNION ALL
SELECT 'US-MA', 'Worcester'
UNION ALL
SELECT 'US-WA', 'Seattle'
UNION ALL
SELECT 'US-WA', 'Spokane'
UNION ALL
SELECT 'US-GA', 'Atlanta'
UNION ALL
SELECT 'US-GA', 'Savannah'
UNION ALL
SELECT 'US-NV', 'Las Vegas'
UNION ALL
SELECT 'US-NV', 'Reno'
UNION ALL
SELECT 'US-MI', 'Detroit'
UNION ALL
SELECT 'US-MI', 'Grand Rapids'
UNION ALL
SELECT 'US-MN', 'Minneapolis'
UNION ALL
SELECT 'US-MN', 'Saint Paul'
UNION ALL
SELECT 'US-OH', 'Columbus'
UNION ALL
SELECT 'US-OH', 'Cleveland'
UNION ALL
SELECT 'US-OR', 'Portland'
UNION ALL
SELECT 'US-OR', 'Salem'
UNION ALL
SELECT 'US-TN', 'Nashville'
UNION ALL
SELECT 'US-TN', 'Memphis'
UNION ALL
SELECT 'US-VA', 'Richmond'
UNION ALL
SELECT 'US-VA', 'Virginia Beach'
UNION ALL
SELECT 'US-MD', 'Baltimore'
UNION ALL
SELECT 'US-MD', 'Frederick'
UNION ALL
SELECT 'US-DC', 'Washington'
UNION ALL
SELECT 'US-UT', 'Salt Lake City'
UNION ALL
SELECT 'US-UT', 'Provo'
UNION ALL
SELECT 'US-LA', 'New Orleans'
UNION ALL
SELECT 'US-LA', 'Baton Rouge'
UNION ALL
SELECT 'US-KY', 'Louisville'
UNION ALL
SELECT 'US-KY', 'Lexington'
UNION ALL
SELECT 'US-IA', 'Des Moines'
UNION ALL
SELECT 'US-IA', 'Cedar Rapids'
UNION ALL
SELECT 'US-OK', 'Oklahoma City'
UNION ALL
SELECT 'US-OK', 'Tulsa'
UNION ALL
SELECT 'US-NE', 'Omaha'
UNION ALL
SELECT 'US-NE', 'Lincoln'
UNION ALL
SELECT 'US-MO', 'Kansas City'
UNION ALL
SELECT 'US-MO', 'St. Louis'
UNION ALL
SELECT 'US-NC', 'Charlotte'
UNION ALL
SELECT 'US-NC', 'Raleigh'
UNION ALL
SELECT 'US-SC', 'Columbia'
UNION ALL
SELECT 'US-SC', 'Charleston'
UNION ALL
SELECT 'US-WI', 'Milwaukee'
UNION ALL
SELECT 'US-WI', 'Madison'
UNION ALL
SELECT 'US-MN', 'Duluth'
UNION ALL
SELECT 'US-AK', 'Anchorage'
UNION ALL
SELECT 'US-HI', 'Honolulu'
-- Canada
UNION ALL
SELECT 'CA-ON', 'Toronto'
UNION ALL
SELECT 'CA-ON', 'Ottawa'
UNION ALL
SELECT 'CA-QC', N'Montréal'
UNION ALL
SELECT 'CA-QC', N'Québec City'
UNION ALL
SELECT 'CA-BC', 'Vancouver'
UNION ALL
SELECT 'CA-BC', 'Victoria'
UNION ALL
SELECT 'CA-AB', 'Calgary'
UNION ALL
SELECT 'CA-AB', 'Edmonton'
UNION ALL
SELECT 'CA-MB', 'Winnipeg'
UNION ALL
SELECT 'CA-NS', 'Halifax'
UNION ALL
SELECT 'CA-SK', 'Saskatoon'
UNION ALL
SELECT 'CA-SK', 'Regina'
UNION ALL
SELECT 'CA-NB', 'Moncton'
UNION ALL
SELECT 'CA-NB', 'Saint John'
UNION ALL
SELECT 'CA-PE', 'Charlottetown'
UNION ALL
SELECT 'CA-NL', N'St. John''s'
UNION ALL
SELECT 'CA-ON', 'Hamilton'
UNION ALL
SELECT 'CA-ON', 'London'
UNION ALL
SELECT 'CA-QC', 'Gatineau'
UNION ALL
SELECT 'CA-QC', 'Laval'
UNION ALL
SELECT 'CA-BC', 'Kelowna'
UNION ALL
SELECT 'CA-AB', 'Red Deer'
UNION ALL
SELECT 'CA-MB', 'Brandon'
-- MEXICO
UNION ALL
SELECT 'MX-CMX', N'Ciudad de México'
UNION ALL
SELECT 'MX-JAL', 'Guadalajara'
UNION ALL
SELECT 'MX-NLE', 'Monterrey'
UNION ALL
SELECT 'MX-PUE', 'Puebla'
UNION ALL
SELECT 'MX-ROO', N'Cancún'
UNION ALL
SELECT 'MX-GUA', 'Guanajuato'
UNION ALL
SELECT 'MX-MIC', 'Morelia'
UNION ALL
SELECT 'MX-BCN', 'Tijuana'
UNION ALL
SELECT 'MX-JAL', 'Zapopan'
UNION ALL
SELECT 'MX-NLE', N'San Nicolás'
UNION ALL
SELECT 'MX-CAM', 'Campeche'
UNION ALL
SELECT 'MX-TAB', 'Villahermosa'
UNION ALL
SELECT 'MX-VER', 'Veracruz'
UNION ALL
SELECT 'MX-OAX', 'Oaxaca'
UNION ALL
SELECT 'MX-SLP', N'San Luis Potosí'
UNION ALL
SELECT 'MX-CHH', 'Chihuahua'
UNION ALL
SELECT 'MX-AGU', 'Aguascalientes'
UNION ALL
SELECT 'MX-MEX', 'Toluca'
UNION ALL
SELECT 'MX-COA', 'Saltillo'
UNION ALL
SELECT 'MX-BCS', 'La Paz'
UNION ALL
SELECT 'MX-NAY', 'Tepic'
UNION ALL
SELECT 'MX-ZAC', 'Zacatecas'
)
INSERT INTO dbo.City
(StateProvinceID, CityName)
SELECT
dbo.UDF_GetStateProvinceIdByCode(c.StateProvinceISO2),
c.CityName
FROM Cities AS c
WHERE NOT EXISTS (
SELECT 1
FROM dbo.City AS ci
WHERE ci.CityName = c.CityName
AND ci.StateProvinceID = dbo.UDF_GetStateProvinceIdByCode(c.StateProvinceISO2)
);
COMMIT TRANSACTION;
END;
GO

View File

@@ -0,0 +1,136 @@
USE Biergarten;
GO
CREATE OR ALTER PROCEDURE dbo.USP_AddTestUsers
AS
BEGIN
SET NOCOUNT ON;
SET XACT_ABORT ON;
BEGIN TRANSACTION;
DECLARE @FullNames TABLE
(FirstName NVARCHAR(128),
LastName NVARCHAR(128));
INSERT INTO @FullNames
(FirstName, LastName)
VALUES
('Aarya', 'Mathews'),
('Aiden', 'Wells'),
('Aleena', 'Gonzalez'),
('Alessandra', 'Nelson'),
('Amari', 'Tucker'),
('Ameer', 'Huff'),
('Amirah', 'Hicks'),
('Analia', 'Dominguez'),
('Anne', 'Jenkins'),
('Apollo', 'Davis'),
('Arianna', 'White'),
('Aubree', 'Moore'),
('Aubrielle', 'Raymond'),
('Aydin', 'Odom'),
('Bowen', 'Casey'),
('Brock', 'Huber'),
('Caiden', 'Strong'),
('Cecilia', 'Rosales'),
('Celeste', 'Barber'),
('Chance', 'Small'),
('Clara', 'Roberts'),
('Collins', 'Brandt'),
('Damir', 'Wallace'),
('Declan', 'Crawford'),
('Dennis', 'Decker'),
('Dylan', 'Lang'),
('Eliza', 'Kane'),
('Elle', 'Poole'),
('Elliott', 'Miles'),
('Emelia', 'Lucas'),
('Emilia', 'Simpson'),
('Emmett', 'Lugo'),
('Ethan', 'Stephens'),
('Etta', 'Woods'),
('Gael', 'Moran'),
('Grant', 'Benson'),
('Gwen', 'James'),
('Huxley', 'Chen'),
('Isabella', 'Fisher'),
('Ivan', 'Mathis'),
('Jamir', 'McMillan'),
('Jaxson', 'Shields'),
('Jimmy', 'Richmond'),
('Josiah', 'Flores'),
('Kaden', 'Enriquez'),
('Kai', 'Lawson'),
('Karsyn', 'Adkins'),
('Karsyn', 'Proctor'),
('Kayden', 'Henson'),
('Kaylie', 'Spears'),
('Kinslee', 'Jones'),
('Kora', 'Guerra'),
('Lane', 'Skinner'),
('Laylani', 'Christian'),
('Ledger', 'Carroll'),
('Leilany', 'Small'),
('Leland', 'McCall'),
('Leonard', 'Calhoun'),
('Levi', 'Ochoa'),
('Lillie', 'Vang'),
('Lola', 'Sheppard'),
('Luciana', 'Poole'),
('Maddox', 'Hughes'),
('Mara', 'Blackwell'),
('Marcellus', 'Bartlett'),
('Margo', 'Koch'),
('Maurice', 'Gibson'),
('Maxton', 'Dodson'),
('Mia', 'Parrish'),
('Millie', 'Fuentes'),
('Nellie', 'Villanueva'),
('Nicolas', 'Mata'),
('Nicolas', 'Miller'),
('Oakleigh', 'Foster'),
('Octavia', 'Pierce'),
('Paisley', 'Allison'),
('Quincy', 'Andersen'),
('Quincy', 'Frazier'),
('Raiden', 'Roberts'),
('Raquel', 'Lara'),
('Rudy', 'McIntosh'),
('Salvador', 'Stein'),
('Samantha', 'Dickson'),
('Solomon', 'Richards'),
('Sylvia', 'Hanna'),
('Talia', 'Trujillo'),
('Thalia', 'Farrell'),
('Trent', 'Mayo'),
('Trinity', 'Cummings'),
('Ty', 'Perry'),
('Tyler', 'Romero'),
('Valeria', 'Pierce'),
('Vance', 'Neal'),
('Whitney', 'Bell'),
('Wilder', 'Graves'),
('William', 'Logan'),
('Zara', 'Wilkinson'),
('Zaria', 'Gibson'),
('Zion', 'Watkins'),
('Zoie', 'Armstrong');
INSERT INTO dbo.UserAccount
(Username, FirstName, LastName, Email, DateOfBirth)
SELECT
LEFT(LOWER(CONCAT(fn.FirstName, '.', fn.LastName)), 64) AS Username,
fn.FirstName,
fn.LastName,
LEFT(LOWER(CONCAT(fn.FirstName, '.', fn.LastName, '@example.com')), 128) AS Email,
-- date of birth: pick age between 18 and 47 (18 + 0..29)
DATEADD(YEAR, -(19 + ABS(CHECKSUM(NEWID())) % 30), CAST(GETDATE() AS DATE))
FROM @FullNames AS fn;
COMMIT TRANSACTION;
END;
GO

View File

@@ -0,0 +1,33 @@
USE Biergarten;
GO
IF TYPE_ID(N'dbo.TblUserHashes') IS NULL
EXEC('CREATE TYPE dbo.TblUserHashes AS TABLE
(
UserAccountId UNIQUEIDENTIFIER NOT NULL,
Hash NVARCHAR(MAX) NOT NULL
);');
GO
-- Stored procedure to insert Argon2 hashes
CREATE OR ALTER PROCEDURE dbo.USP_AddUserCredentials
(
@Hash dbo.TblUserHashes READONLY
)
AS
BEGIN
SET NOCOUNT ON;
SET XACT_ABORT ON;
BEGIN TRANSACTION;
INSERT INTO dbo.UserCredential
(UserAccountId, Hash)
SELECT
uah.UserAccountId,
uah.Hash
FROM @Hash AS uah;
COMMIT TRANSACTION;
END;
GO

View File

@@ -0,0 +1,35 @@
USE Biergarten;
GO
CREATE OR ALTER PROCEDURE dbo.USP_CreateUserVerification
AS
BEGIN
SET NOCOUNT ON;
SET XACT_ABORT ON;
BEGIN TRANSACTION;
INSERT INTO dbo.UserVerification
(UserAccountId)
SELECT
ua.UserAccountID
FROM dbo.UserAccount AS ua
WHERE NOT EXISTS
(SELECT 1
FROM dbo.UserVerification AS uv
WHERE uv.UserAccountId = ua.UserAccountID);
IF (SELECT COUNT(*)
FROM dbo.UserVerification)
!= (SELECT COUNT(*)
FROM dbo.UserAccount)
BEGIN
RAISERROR('UserVerification count does not match UserAccount count after insertion.', 16, 1);
ROLLBACK TRANSACTION;
RETURN;
END
COMMIT TRANSACTION;
END
GO