diff --git a/.gitignore b/.gitignore index 69bbe5d..37f801a 100644 --- a/.gitignore +++ b/.gitignore @@ -430,4 +430,5 @@ FodyWeavers.xsd .DS_Store */data_source/other -.fake \ No newline at end of file +.fake +.idea \ No newline at end of file diff --git a/BusinessLayer/Services/UserService.cs b/BusinessLayer/Services/UserService.cs index 1ab5e1a..a923393 100644 --- a/BusinessLayer/Services/UserService.cs +++ b/BusinessLayer/Services/UserService.cs @@ -1,5 +1,6 @@ using DataAccessLayer; using DataAccessLayer.Entities; +using DataAccessLayer.Repositories; namespace BusinessLayer.Services { diff --git a/DALTests/UserAccountRepositoryTests.cs b/DALTests/UserAccountRepositoryTests.cs index d02d34f..34e5229 100644 --- a/DALTests/UserAccountRepositoryTests.cs +++ b/DALTests/UserAccountRepositoryTests.cs @@ -1,20 +1,12 @@ -using System; -using System.Collections.Generic; -using System.Linq; using DataAccessLayer; using DataAccessLayer.Entities; -using Xunit; +using DataAccessLayer.Repositories; namespace DALTests { public class UserAccountRepositoryTests { - private readonly IUserAccountRepository _repository; - - public UserAccountRepositoryTests() - { - _repository = new UserAccountRepository(); - } + private readonly IUserAccountRepository _repository = new UserAccountRepository(); [Fact] public void Add_ShouldInsertUserAccount() @@ -22,7 +14,7 @@ namespace DALTests // Arrange var userAccount = new UserAccount { - UserAccountID = Guid.NewGuid(), + UserAccountId = Guid.NewGuid(), Username = "testuser", FirstName = "Test", LastName = "User", @@ -33,7 +25,7 @@ namespace DALTests // Act _repository.Add(userAccount); - var retrievedUser = _repository.GetById(userAccount.UserAccountID); + var retrievedUser = _repository.GetById(userAccount.UserAccountId); // Assert Assert.NotNull(retrievedUser); @@ -47,7 +39,7 @@ namespace DALTests var userId = Guid.NewGuid(); var userAccount = new UserAccount { - UserAccountID = userId, + UserAccountId = userId, Username = "existinguser", FirstName = "Existing", LastName = "User", @@ -62,7 +54,7 @@ namespace DALTests // Assert Assert.NotNull(retrievedUser); - Assert.Equal(userId, retrievedUser.UserAccountID); + Assert.Equal(userId, retrievedUser.UserAccountId); } [Fact] @@ -71,7 +63,7 @@ namespace DALTests // Arrange var userAccount = new UserAccount { - UserAccountID = Guid.NewGuid(), + UserAccountId = Guid.NewGuid(), Username = "updatableuser", FirstName = "Updatable", LastName = "User", @@ -84,7 +76,7 @@ namespace DALTests // Act userAccount.FirstName = "Updated"; _repository.Update(userAccount); - var updatedUser = _repository.GetById(userAccount.UserAccountID); + var updatedUser = _repository.GetById(userAccount.UserAccountId); // Assert Assert.NotNull(updatedUser); @@ -97,7 +89,7 @@ namespace DALTests // Arrange var userAccount = new UserAccount { - UserAccountID = Guid.NewGuid(), + UserAccountId = Guid.NewGuid(), Username = "deletableuser", FirstName = "Deletable", LastName = "User", @@ -108,8 +100,8 @@ namespace DALTests _repository.Add(userAccount); // Act - _repository.Delete(userAccount.UserAccountID); - var deletedUser = _repository.GetById(userAccount.UserAccountID); + _repository.Delete(userAccount.UserAccountId); + var deletedUser = _repository.GetById(userAccount.UserAccountId); // Assert Assert.Null(deletedUser); @@ -121,7 +113,7 @@ namespace DALTests // Arrange var user1 = new UserAccount { - UserAccountID = Guid.NewGuid(), + UserAccountId = Guid.NewGuid(), Username = "user1", FirstName = "User", LastName = "One", @@ -131,7 +123,7 @@ namespace DALTests }; var user2 = new UserAccount { - UserAccountID = Guid.NewGuid(), + UserAccountId = Guid.NewGuid(), Username = "user2", FirstName = "User", LastName = "Two", @@ -158,7 +150,7 @@ namespace DALTests { new UserAccount { - UserAccountID = Guid.NewGuid(), + UserAccountId = Guid.NewGuid(), Username = $"pageuser_{Guid.NewGuid():N}", FirstName = "Page", LastName = "User", @@ -168,7 +160,7 @@ namespace DALTests }, new UserAccount { - UserAccountID = Guid.NewGuid(), + UserAccountId = Guid.NewGuid(), Username = $"pageuser_{Guid.NewGuid():N}", FirstName = "Page", LastName = "User", @@ -178,7 +170,7 @@ namespace DALTests }, new UserAccount { - UserAccountID = Guid.NewGuid(), + UserAccountId = Guid.NewGuid(), Username = $"pageuser_{Guid.NewGuid():N}", FirstName = "Page", LastName = "User", diff --git a/DBSeed/DBSeed.csproj b/DBSeed/DBSeed.csproj index 958ec61..54b70c3 100644 --- a/DBSeed/DBSeed.csproj +++ b/DBSeed/DBSeed.csproj @@ -12,6 +12,10 @@ Include="Konscious.Security.Cryptography.Argon2" Version="1.3.1" /> - + + + + + diff --git a/DBSeed/ISeeder.cs b/DBSeed/ISeeder.cs index 4624827..1ecf897 100644 --- a/DBSeed/ISeeder.cs +++ b/DBSeed/ISeeder.cs @@ -1,6 +1,9 @@ using Microsoft.Data.SqlClient; -interface ISeeder +namespace DBSeed { - Task SeedAsync(SqlConnection connection); + internal interface ISeeder + { + Task SeedAsync(SqlConnection connection); + } } \ No newline at end of file diff --git a/DBSeed/LocationSeeder.cs b/DBSeed/LocationSeeder.cs index 983921b..52d3d78 100644 --- a/DBSeed/LocationSeeder.cs +++ b/DBSeed/LocationSeeder.cs @@ -1,330 +1,328 @@ using System.Data; using Microsoft.Data.SqlClient; -namespace DBSeed; - -class LocationSeeder : ISeeder +namespace DBSeed { - private static readonly IReadOnlyList<( - string CountryName, - string CountryCode - )> Countries = - [ - ("Canada", "CA"), - ("Mexico", "MX"), - ("United States", "US"), - ]; - private static readonly IReadOnlyList<( - string StateProvinceName, - string StateProvinceCode, - string CountryCode - )> States = - [ - ("Alabama", "US-AL", "US"), - ("Alaska", "US-AK", "US"), - ("Arizona", "US-AZ", "US"), - ("Arkansas", "US-AR", "US"), - ("California", "US-CA", "US"), - ("Colorado", "US-CO", "US"), - ("Connecticut", "US-CT", "US"), - ("Delaware", "US-DE", "US"), - ("Florida", "US-FL", "US"), - ("Georgia", "US-GA", "US"), - ("Hawaii", "US-HI", "US"), - ("Idaho", "US-ID", "US"), - ("Illinois", "US-IL", "US"), - ("Indiana", "US-IN", "US"), - ("Iowa", "US-IA", "US"), - ("Kansas", "US-KS", "US"), - ("Kentucky", "US-KY", "US"), - ("Louisiana", "US-LA", "US"), - ("Maine", "US-ME", "US"), - ("Maryland", "US-MD", "US"), - ("Massachusetts", "US-MA", "US"), - ("Michigan", "US-MI", "US"), - ("Minnesota", "US-MN", "US"), - ("Mississippi", "US-MS", "US"), - ("Missouri", "US-MO", "US"), - ("Montana", "US-MT", "US"), - ("Nebraska", "US-NE", "US"), - ("Nevada", "US-NV", "US"), - ("New Hampshire", "US-NH", "US"), - ("New Jersey", "US-NJ", "US"), - ("New Mexico", "US-NM", "US"), - ("New York", "US-NY", "US"), - ("North Carolina", "US-NC", "US"), - ("North Dakota", "US-ND", "US"), - ("Ohio", "US-OH", "US"), - ("Oklahoma", "US-OK", "US"), - ("Oregon", "US-OR", "US"), - ("Pennsylvania", "US-PA", "US"), - ("Rhode Island", "US-RI", "US"), - ("South Carolina", "US-SC", "US"), - ("South Dakota", "US-SD", "US"), - ("Tennessee", "US-TN", "US"), - ("Texas", "US-TX", "US"), - ("Utah", "US-UT", "US"), - ("Vermont", "US-VT", "US"), - ("Virginia", "US-VA", "US"), - ("Washington", "US-WA", "US"), - ("West Virginia", "US-WV", "US"), - ("Wisconsin", "US-WI", "US"), - ("Wyoming", "US-WY", "US"), - ("District of Columbia", "US-DC", "US"), - ("Puerto Rico", "US-PR", "US"), - ("U.S. Virgin Islands", "US-VI", "US"), - ("Guam", "US-GU", "US"), - ("Northern Mariana Islands", "US-MP", "US"), - ("American Samoa", "US-AS", "US"), - ("Ontario", "CA-ON", "CA"), - ("Québec", "CA-QC", "CA"), - ("Nova Scotia", "CA-NS", "CA"), - ("New Brunswick", "CA-NB", "CA"), - ("Manitoba", "CA-MB", "CA"), - ("British Columbia", "CA-BC", "CA"), - ("Prince Edward Island", "CA-PE", "CA"), - ("Saskatchewan", "CA-SK", "CA"), - ("Alberta", "CA-AB", "CA"), - ("Newfoundland and Labrador", "CA-NL", "CA"), - ("Northwest Territories", "CA-NT", "CA"), - ("Yukon", "CA-YT", "CA"), - ("Nunavut", "CA-NU", "CA"), - ("Aguascalientes", "MX-AGU", "MX"), - ("Baja California", "MX-BCN", "MX"), - ("Baja California Sur", "MX-BCS", "MX"), - ("Campeche", "MX-CAM", "MX"), - ("Chiapas", "MX-CHP", "MX"), - ("Chihuahua", "MX-CHH", "MX"), - ("Coahuila de Zaragoza", "MX-COA", "MX"), - ("Colima", "MX-COL", "MX"), - ("Durango", "MX-DUR", "MX"), - ("Guanajuato", "MX-GUA", "MX"), - ("Guerrero", "MX-GRO", "MX"), - ("Hidalgo", "MX-HID", "MX"), - ("Jalisco", "MX-JAL", "MX"), - ("México State", "MX-MEX", "MX"), - ("Michoacán de Ocampo", "MX-MIC", "MX"), - ("Morelos", "MX-MOR", "MX"), - ("Nayarit", "MX-NAY", "MX"), - ("Nuevo León", "MX-NLE", "MX"), - ("Oaxaca", "MX-OAX", "MX"), - ("Puebla", "MX-PUE", "MX"), - ("Querétaro", "MX-QUE", "MX"), - ("Quintana Roo", "MX-ROO", "MX"), - ("San Luis Potosí", "MX-SLP", "MX"), - ("Sinaloa", "MX-SIN", "MX"), - ("Sonora", "MX-SON", "MX"), - ("Tabasco", "MX-TAB", "MX"), - ("Tamaulipas", "MX-TAM", "MX"), - ("Tlaxcala", "MX-TLA", "MX"), - ("Veracruz de Ignacio de la Llave", "MX-VER", "MX"), - ("Yucatán", "MX-YUC", "MX"), - ("Zacatecas", "MX-ZAC", "MX"), - ("Ciudad de México", "MX-CMX", "MX"), - ]; - - private static readonly IReadOnlyList<( - string StateProvinceCode, - string CityName - )> Cities = - [ - ("US-CA", "Los Angeles"), - ("US-CA", "San Diego"), - ("US-CA", "San Francisco"), - ("US-CA", "Sacramento"), - ("US-TX", "Houston"), - ("US-TX", "Dallas"), - ("US-TX", "Austin"), - ("US-TX", "San Antonio"), - ("US-FL", "Miami"), - ("US-FL", "Orlando"), - ("US-FL", "Tampa"), - ("US-NY", "New York"), - ("US-NY", "Buffalo"), - ("US-NY", "Rochester"), - ("US-IL", "Chicago"), - ("US-IL", "Springfield"), - ("US-PA", "Philadelphia"), - ("US-PA", "Pittsburgh"), - ("US-AZ", "Phoenix"), - ("US-AZ", "Tucson"), - ("US-CO", "Denver"), - ("US-CO", "Colorado Springs"), - ("US-MA", "Boston"), - ("US-MA", "Worcester"), - ("US-WA", "Seattle"), - ("US-WA", "Spokane"), - ("US-GA", "Atlanta"), - ("US-GA", "Savannah"), - ("US-NV", "Las Vegas"), - ("US-NV", "Reno"), - ("US-MI", "Detroit"), - ("US-MI", "Grand Rapids"), - ("US-MN", "Minneapolis"), - ("US-MN", "Saint Paul"), - ("US-OH", "Columbus"), - ("US-OH", "Cleveland"), - ("US-OR", "Portland"), - ("US-OR", "Salem"), - ("US-TN", "Nashville"), - ("US-TN", "Memphis"), - ("US-VA", "Richmond"), - ("US-VA", "Virginia Beach"), - ("US-MD", "Baltimore"), - ("US-MD", "Frederick"), - ("US-DC", "Washington"), - ("US-UT", "Salt Lake City"), - ("US-UT", "Provo"), - ("US-LA", "New Orleans"), - ("US-LA", "Baton Rouge"), - ("US-KY", "Louisville"), - ("US-KY", "Lexington"), - ("US-IA", "Des Moines"), - ("US-IA", "Cedar Rapids"), - ("US-OK", "Oklahoma City"), - ("US-OK", "Tulsa"), - ("US-NE", "Omaha"), - ("US-NE", "Lincoln"), - ("US-MO", "Kansas City"), - ("US-MO", "St. Louis"), - ("US-NC", "Charlotte"), - ("US-NC", "Raleigh"), - ("US-SC", "Columbia"), - ("US-SC", "Charleston"), - ("US-WI", "Milwaukee"), - ("US-WI", "Madison"), - ("US-MN", "Duluth"), - ("US-AK", "Anchorage"), - ("US-HI", "Honolulu"), - ("CA-ON", "Toronto"), - ("CA-ON", "Ottawa"), - ("CA-QC", "Montréal"), - ("CA-QC", "Québec City"), - ("CA-BC", "Vancouver"), - ("CA-BC", "Victoria"), - ("CA-AB", "Calgary"), - ("CA-AB", "Edmonton"), - ("CA-MB", "Winnipeg"), - ("CA-NS", "Halifax"), - ("CA-SK", "Saskatoon"), - ("CA-SK", "Regina"), - ("CA-NB", "Moncton"), - ("CA-NB", "Saint John"), - ("CA-PE", "Charlottetown"), - ("CA-NL", "St. John's"), - ("CA-ON", "Hamilton"), - ("CA-ON", "London"), - ("CA-QC", "Gatineau"), - ("CA-QC", "Laval"), - ("CA-BC", "Kelowna"), - ("CA-AB", "Red Deer"), - ("CA-MB", "Brandon"), - ("MX-CMX", "Ciudad de México"), - ("MX-JAL", "Guadalajara"), - ("MX-NLE", "Monterrey"), - ("MX-PUE", "Puebla"), - ("MX-ROO", "Cancún"), - ("MX-GUA", "Guanajuato"), - ("MX-MIC", "Morelia"), - ("MX-BCN", "Tijuana"), - ("MX-JAL", "Zapopan"), - ("MX-NLE", "San Nicolás"), - ("MX-CAM", "Campeche"), - ("MX-TAB", "Villahermosa"), - ("MX-VER", "Veracruz"), - ("MX-OAX", "Oaxaca"), - ("MX-SLP", "San Luis Potosí"), - ("MX-CHH", "Chihuahua"), - ("MX-AGU", "Aguascalientes"), - ("MX-MEX", "Toluca"), - ("MX-COA", "Saltillo"), - ("MX-BCS", "La Paz"), - ("MX-NAY", "Tepic"), - ("MX-ZAC", "Zacatecas"), - ]; - - public async Task SeedAsync(SqlConnection connection) + internal class LocationSeeder : ISeeder { - foreach (var (countryName, countryCode) in Countries) + private static readonly IReadOnlyList<( + string CountryName, + string CountryCode + )> Countries = + [ + ("Canada", "CA"), + ("Mexico", "MX"), + ("United States", "US"), + ]; + + private static IReadOnlyList<(string StateProvinceName, string StateProvinceCode, string CountryCode)> States { - await CreateCountryAsync(connection, countryName, countryCode); + get; + } = + [ + ("Alabama", "US-AL", "US"), + ("Alaska", "US-AK", "US"), + ("Arizona", "US-AZ", "US"), + ("Arkansas", "US-AR", "US"), + ("California", "US-CA", "US"), + ("Colorado", "US-CO", "US"), + ("Connecticut", "US-CT", "US"), + ("Delaware", "US-DE", "US"), + ("Florida", "US-FL", "US"), + ("Georgia", "US-GA", "US"), + ("Hawaii", "US-HI", "US"), + ("Idaho", "US-ID", "US"), + ("Illinois", "US-IL", "US"), + ("Indiana", "US-IN", "US"), + ("Iowa", "US-IA", "US"), + ("Kansas", "US-KS", "US"), + ("Kentucky", "US-KY", "US"), + ("Louisiana", "US-LA", "US"), + ("Maine", "US-ME", "US"), + ("Maryland", "US-MD", "US"), + ("Massachusetts", "US-MA", "US"), + ("Michigan", "US-MI", "US"), + ("Minnesota", "US-MN", "US"), + ("Mississippi", "US-MS", "US"), + ("Missouri", "US-MO", "US"), + ("Montana", "US-MT", "US"), + ("Nebraska", "US-NE", "US"), + ("Nevada", "US-NV", "US"), + ("New Hampshire", "US-NH", "US"), + ("New Jersey", "US-NJ", "US"), + ("New Mexico", "US-NM", "US"), + ("New York", "US-NY", "US"), + ("North Carolina", "US-NC", "US"), + ("North Dakota", "US-ND", "US"), + ("Ohio", "US-OH", "US"), + ("Oklahoma", "US-OK", "US"), + ("Oregon", "US-OR", "US"), + ("Pennsylvania", "US-PA", "US"), + ("Rhode Island", "US-RI", "US"), + ("South Carolina", "US-SC", "US"), + ("South Dakota", "US-SD", "US"), + ("Tennessee", "US-TN", "US"), + ("Texas", "US-TX", "US"), + ("Utah", "US-UT", "US"), + ("Vermont", "US-VT", "US"), + ("Virginia", "US-VA", "US"), + ("Washington", "US-WA", "US"), + ("West Virginia", "US-WV", "US"), + ("Wisconsin", "US-WI", "US"), + ("Wyoming", "US-WY", "US"), + ("District of Columbia", "US-DC", "US"), + ("Puerto Rico", "US-PR", "US"), + ("U.S. Virgin Islands", "US-VI", "US"), + ("Guam", "US-GU", "US"), + ("Northern Mariana Islands", "US-MP", "US"), + ("American Samoa", "US-AS", "US"), + ("Ontario", "CA-ON", "CA"), + ("Québec", "CA-QC", "CA"), + ("Nova Scotia", "CA-NS", "CA"), + ("New Brunswick", "CA-NB", "CA"), + ("Manitoba", "CA-MB", "CA"), + ("British Columbia", "CA-BC", "CA"), + ("Prince Edward Island", "CA-PE", "CA"), + ("Saskatchewan", "CA-SK", "CA"), + ("Alberta", "CA-AB", "CA"), + ("Newfoundland and Labrador", "CA-NL", "CA"), + ("Northwest Territories", "CA-NT", "CA"), + ("Yukon", "CA-YT", "CA"), + ("Nunavut", "CA-NU", "CA"), + ("Aguascalientes", "MX-AGU", "MX"), + ("Baja California", "MX-BCN", "MX"), + ("Baja California Sur", "MX-BCS", "MX"), + ("Campeche", "MX-CAM", "MX"), + ("Chiapas", "MX-CHP", "MX"), + ("Chihuahua", "MX-CHH", "MX"), + ("Coahuila de Zaragoza", "MX-COA", "MX"), + ("Colima", "MX-COL", "MX"), + ("Durango", "MX-DUR", "MX"), + ("Guanajuato", "MX-GUA", "MX"), + ("Guerrero", "MX-GRO", "MX"), + ("Hidalgo", "MX-HID", "MX"), + ("Jalisco", "MX-JAL", "MX"), + ("México State", "MX-MEX", "MX"), + ("Michoacán de Ocampo", "MX-MIC", "MX"), + ("Morelos", "MX-MOR", "MX"), + ("Nayarit", "MX-NAY", "MX"), + ("Nuevo León", "MX-NLE", "MX"), + ("Oaxaca", "MX-OAX", "MX"), + ("Puebla", "MX-PUE", "MX"), + ("Querétaro", "MX-QUE", "MX"), + ("Quintana Roo", "MX-ROO", "MX"), + ("San Luis Potosí", "MX-SLP", "MX"), + ("Sinaloa", "MX-SIN", "MX"), + ("Sonora", "MX-SON", "MX"), + ("Tabasco", "MX-TAB", "MX"), + ("Tamaulipas", "MX-TAM", "MX"), + ("Tlaxcala", "MX-TLA", "MX"), + ("Veracruz de Ignacio de la Llave", "MX-VER", "MX"), + ("Yucatán", "MX-YUC", "MX"), + ("Zacatecas", "MX-ZAC", "MX"), + ("Ciudad de México", "MX-CMX", "MX"), + ]; + + private static IReadOnlyList<(string StateProvinceCode, string CityName)> Cities { get; } = + [ + ("US-CA", "Los Angeles"), + ("US-CA", "San Diego"), + ("US-CA", "San Francisco"), + ("US-CA", "Sacramento"), + ("US-TX", "Houston"), + ("US-TX", "Dallas"), + ("US-TX", "Austin"), + ("US-TX", "San Antonio"), + ("US-FL", "Miami"), + ("US-FL", "Orlando"), + ("US-FL", "Tampa"), + ("US-NY", "New York"), + ("US-NY", "Buffalo"), + ("US-NY", "Rochester"), + ("US-IL", "Chicago"), + ("US-IL", "Springfield"), + ("US-PA", "Philadelphia"), + ("US-PA", "Pittsburgh"), + ("US-AZ", "Phoenix"), + ("US-AZ", "Tucson"), + ("US-CO", "Denver"), + ("US-CO", "Colorado Springs"), + ("US-MA", "Boston"), + ("US-MA", "Worcester"), + ("US-WA", "Seattle"), + ("US-WA", "Spokane"), + ("US-GA", "Atlanta"), + ("US-GA", "Savannah"), + ("US-NV", "Las Vegas"), + ("US-NV", "Reno"), + ("US-MI", "Detroit"), + ("US-MI", "Grand Rapids"), + ("US-MN", "Minneapolis"), + ("US-MN", "Saint Paul"), + ("US-OH", "Columbus"), + ("US-OH", "Cleveland"), + ("US-OR", "Portland"), + ("US-OR", "Salem"), + ("US-TN", "Nashville"), + ("US-TN", "Memphis"), + ("US-VA", "Richmond"), + ("US-VA", "Virginia Beach"), + ("US-MD", "Baltimore"), + ("US-MD", "Frederick"), + ("US-DC", "Washington"), + ("US-UT", "Salt Lake City"), + ("US-UT", "Provo"), + ("US-LA", "New Orleans"), + ("US-LA", "Baton Rouge"), + ("US-KY", "Louisville"), + ("US-KY", "Lexington"), + ("US-IA", "Des Moines"), + ("US-IA", "Cedar Rapids"), + ("US-OK", "Oklahoma City"), + ("US-OK", "Tulsa"), + ("US-NE", "Omaha"), + ("US-NE", "Lincoln"), + ("US-MO", "Kansas City"), + ("US-MO", "St. Louis"), + ("US-NC", "Charlotte"), + ("US-NC", "Raleigh"), + ("US-SC", "Columbia"), + ("US-SC", "Charleston"), + ("US-WI", "Milwaukee"), + ("US-WI", "Madison"), + ("US-MN", "Duluth"), + ("US-AK", "Anchorage"), + ("US-HI", "Honolulu"), + ("CA-ON", "Toronto"), + ("CA-ON", "Ottawa"), + ("CA-QC", "Montréal"), + ("CA-QC", "Québec City"), + ("CA-BC", "Vancouver"), + ("CA-BC", "Victoria"), + ("CA-AB", "Calgary"), + ("CA-AB", "Edmonton"), + ("CA-MB", "Winnipeg"), + ("CA-NS", "Halifax"), + ("CA-SK", "Saskatoon"), + ("CA-SK", "Regina"), + ("CA-NB", "Moncton"), + ("CA-NB", "Saint John"), + ("CA-PE", "Charlottetown"), + ("CA-NL", "St. John's"), + ("CA-ON", "Hamilton"), + ("CA-ON", "London"), + ("CA-QC", "Gatineau"), + ("CA-QC", "Laval"), + ("CA-BC", "Kelowna"), + ("CA-AB", "Red Deer"), + ("CA-MB", "Brandon"), + ("MX-CMX", "Ciudad de México"), + ("MX-JAL", "Guadalajara"), + ("MX-NLE", "Monterrey"), + ("MX-PUE", "Puebla"), + ("MX-ROO", "Cancún"), + ("MX-GUA", "Guanajuato"), + ("MX-MIC", "Morelia"), + ("MX-BCN", "Tijuana"), + ("MX-JAL", "Zapopan"), + ("MX-NLE", "San Nicolás"), + ("MX-CAM", "Campeche"), + ("MX-TAB", "Villahermosa"), + ("MX-VER", "Veracruz"), + ("MX-OAX", "Oaxaca"), + ("MX-SLP", "San Luis Potosí"), + ("MX-CHH", "Chihuahua"), + ("MX-AGU", "Aguascalientes"), + ("MX-MEX", "Toluca"), + ("MX-COA", "Saltillo"), + ("MX-BCS", "La Paz"), + ("MX-NAY", "Tepic"), + ("MX-ZAC", "Zacatecas"), + ]; + + public async Task SeedAsync(SqlConnection connection) + { + foreach (var (countryName, countryCode) in Countries) + { + await CreateCountryAsync(connection, countryName, countryCode); + } + + foreach ( + var (stateProvinceName, stateProvinceCode, countryCode) in States + ) + { + await CreateStateProvinceAsync( + connection, + stateProvinceName, + stateProvinceCode, + countryCode + ); + } + + foreach (var (stateProvinceCode, cityName) in Cities) + { + await CreateCityAsync(connection, cityName, stateProvinceCode); + } } - foreach ( - var (stateProvinceName, stateProvinceCode, countryCode) in States + private static async Task CreateCountryAsync( + SqlConnection connection, + string countryName, + string countryCode ) { - await CreateStateProvinceAsync( - connection, - stateProvinceName, - stateProvinceCode, - countryCode + await using var command = new SqlCommand( + "dbo.USP_CreateCountry", + connection ); + command.CommandType = CommandType.StoredProcedure; + command.Parameters.AddWithValue("@CountryName", countryName); + command.Parameters.AddWithValue("@ISO3616_1", countryCode); + + await command.ExecuteNonQueryAsync(); } - foreach (var (stateProvinceCode, cityName) in Cities) + private static async Task CreateStateProvinceAsync( + SqlConnection connection, + string stateProvinceName, + string stateProvinceCode, + string countryCode + ) { - await CreateCityAsync(connection, cityName, stateProvinceCode); + await using var command = new SqlCommand( + "dbo.USP_CreateStateProvince", + connection + ); + command.CommandType = CommandType.StoredProcedure; + command.Parameters.AddWithValue( + "@StateProvinceName", + stateProvinceName + ); + command.Parameters.AddWithValue("@ISO3616_2", stateProvinceCode); + command.Parameters.AddWithValue("@CountryCode", countryCode); + + await command.ExecuteNonQueryAsync(); + } + + private static async Task CreateCityAsync( + SqlConnection connection, + string cityName, + string stateProvinceCode + ) + { + await using var command = new SqlCommand( + "dbo.USP_CreateCity", + connection + ); + command.CommandType = CommandType.StoredProcedure; + command.Parameters.AddWithValue("@CityName", cityName); + command.Parameters.AddWithValue( + "@StateProvinceCode", + stateProvinceCode + ); + + await command.ExecuteNonQueryAsync(); } } - - private static async Task CreateCountryAsync( - SqlConnection connection, - string countryName, - string countryCode - ) - { - await using var command = new SqlCommand( - "dbo.USP_CreateCountry", - connection - ); - command.CommandType = CommandType.StoredProcedure; - command.Parameters.AddWithValue("@CountryName", countryName); - command.Parameters.AddWithValue("@ISO3616_1", countryCode); - - await command.ExecuteNonQueryAsync(); - } - - private static async Task CreateStateProvinceAsync( - SqlConnection connection, - string stateProvinceName, - string stateProvinceCode, - string countryCode - ) - { - await using var command = new SqlCommand( - "dbo.USP_CreateStateProvince", - connection - ); - command.CommandType = CommandType.StoredProcedure; - command.Parameters.AddWithValue( - "@StateProvinceName", - stateProvinceName - ); - command.Parameters.AddWithValue("@ISO3616_2", stateProvinceCode); - command.Parameters.AddWithValue("@CountryCode", countryCode); - - await command.ExecuteNonQueryAsync(); - } - - private static async Task CreateCityAsync( - SqlConnection connection, - string cityName, - string stateProvinceCode - ) - { - await using var command = new SqlCommand( - "dbo.USP_CreateCity", - connection - ); - command.CommandType = CommandType.StoredProcedure; - command.Parameters.AddWithValue("@CityName", cityName); - command.Parameters.AddWithValue( - "@StateProvinceCode", - stateProvinceCode - ); - - await command.ExecuteNonQueryAsync(); - } -} +} \ No newline at end of file diff --git a/DBSeed/UserSeeder.cs b/DBSeed/UserSeeder.cs index 2918bff..3fd7f64 100644 --- a/DBSeed/UserSeeder.cs +++ b/DBSeed/UserSeeder.cs @@ -1,336 +1,258 @@ using System.Data; using System.Security.Cryptography; using System.Text; +using DataAccessLayer.Entities; +using DataAccessLayer.Repositories; using idunno.Password; using Konscious.Security.Cryptography; using Microsoft.Data.SqlClient; -namespace DBSeed; - -class UserSeeder : ISeeder +namespace DBSeed { - private static readonly IReadOnlyList<( - string FirstName, - string LastName - )> SeedNames = - [ - ("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"), - ]; - public async Task SeedAsync(SqlConnection connection) + internal class UserSeeder : ISeeder { - var generator = new PasswordGenerator(); - var random = new Random(); - int createdUsers = 0; - int createdCredentials = 0; - int createdVerifications = 0; + private UserAccountRepository _userAccountRepository = new UserAccountRepository(); + + + private static readonly IReadOnlyList<( + string FirstName, + string LastName + )> SeedNames = + [ + ("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"), + ]; - foreach (var (firstName, lastName) in SeedNames) + public async Task SeedAsync(SqlConnection connection) { - string username = BuildUsername(firstName, lastName); - string email = BuildEmail(firstName, lastName); - Guid? existingId = - await GetUserAccountIdByUsernameAsync(connection, username) - ?? await GetUserAccountIdByEmailAsync(connection, email); + var generator = new PasswordGenerator(); + var rng = new Random(); + int createdUsers = 0; + int createdCredentials = 0; + int createdVerifications = 0; - Guid userAccountId; - if (existingId.HasValue) + foreach (var (firstName, lastName) in SeedNames) { - userAccountId = existingId.Value; - } - else - { - userAccountId = Guid.NewGuid(); - DateTime dateOfBirth = GenerateDateOfBirth(random); - await CreateUserAccountAsync( - connection, - userAccountId, - username, - firstName, - lastName, - email, - dateOfBirth - ); - createdUsers++; - } + // create the user in the database + var ua = new UserAccount + { + FirstName = firstName, + LastName = lastName, + Email = $"{firstName}.{lastName}@thebiergarten.app", + Username = $"{firstName[0]}.{lastName}", + DateOfBirth = GenerateDateOfBirth(rng) + }; - 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++; - } - if (!await HasUserVerificationAsync(connection, userAccountId)) - { + // 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++; + } + + // add user verification + if (await HasUserVerificationAsync(connection, userAccountId)) continue; await AddUserVerificationAsync(connection, userAccountId); createdVerifications++; } + + Console.WriteLine($"Created {createdUsers} user accounts."); + Console.WriteLine($"Added {createdCredentials} user credentials."); + Console.WriteLine($"Added {createdVerifications} user verifications."); } - Console.WriteLine($"Created {createdUsers} user accounts."); - Console.WriteLine($"Added {createdCredentials} user credentials."); - Console.WriteLine($"Added {createdVerifications} user verifications."); - } - - private static string GeneratePasswordHash(string pwd) - { - byte[] salt = RandomNumberGenerator.GetBytes(16); - - var argon2 = new Argon2id(Encoding.UTF8.GetBytes(pwd)) + private static string GeneratePasswordHash(string pwd) { - Salt = salt, - DegreeOfParallelism = Math.Max(Environment.ProcessorCount, 1), - MemorySize = 65536, - Iterations = 4, - }; + byte[] salt = RandomNumberGenerator.GetBytes(16); - byte[] hash = argon2.GetBytes(32); - return $"{Convert.ToBase64String(salt)}:{Convert.ToBase64String(hash)}"; + var argon2 = new Argon2id(Encoding.UTF8.GetBytes(pwd)) + { + Salt = salt, + DegreeOfParallelism = Math.Max(Environment.ProcessorCount, 1), + MemorySize = 65536, + Iterations = 4, + }; + + byte[] hash = argon2.GetBytes(32); + 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 + ) + { + const string sql = """ + SELECT 1 + FROM dbo.UserVerification + WHERE UserAccountId = @UserAccountId; + """; + await using var command = new SqlCommand(sql, connection); + command.Parameters.AddWithValue("@UserAccountId", userAccountId); + var result = await command.ExecuteScalarAsync(); + return result is not null; + } + + private static async Task AddUserVerificationAsync( + SqlConnection connection, + Guid userAccountId + ) + { + await using var command = new SqlCommand( + "dbo.USP_CreateUserVerification", + connection + ); + command.CommandType = CommandType.StoredProcedure; + command.Parameters.AddWithValue("@UserAccountID", userAccountId); + + await command.ExecuteNonQueryAsync(); + } + + private static DateTime GenerateDateOfBirth(Random random) + { + int age = 19 + random.Next(0, 30); + DateTime baseDate = DateTime.UtcNow.Date.AddYears(-age); + int offsetDays = random.Next(0, 365); + return baseDate.AddDays(-offsetDays); + } } - - private static async Task GetUserAccountIdByUsernameAsync( - SqlConnection connection, - string username - ) - { - await using var command = new SqlCommand( - "usp_GetUserAccountByUsername", - connection - ); - command.CommandType = CommandType.StoredProcedure; - command.Parameters.AddWithValue("@Username", username); - - await using var reader = await command.ExecuteReaderAsync(); - return await reader.ReadAsync() ? reader.GetGuid(0) : null; - } - - private static async Task GetUserAccountIdByEmailAsync( - SqlConnection connection, - string email - ) - { - await using var command = new SqlCommand( - "usp_GetUserAccountByEmail", - connection - ); - command.CommandType = CommandType.StoredProcedure; - command.Parameters.AddWithValue("@Email", email); - - await using var reader = await command.ExecuteReaderAsync(); - return await reader.ReadAsync() ? reader.GetGuid(0) : null; - } - - private static async Task CreateUserAccountAsync( - SqlConnection connection, - Guid userAccountId, - string username, - string firstName, - string lastName, - string email, - DateTime dateOfBirth - ) - { - await using var command = new SqlCommand( - "usp_CreateUserAccount", - connection - ); - command.CommandType = CommandType.StoredProcedure; - command.Parameters.AddWithValue("@UserAccountId", userAccountId); - command.Parameters.AddWithValue("@Username", username); - command.Parameters.AddWithValue("@FirstName", firstName); - command.Parameters.AddWithValue("@LastName", lastName); - command.Parameters.AddWithValue("@DateOfBirth", dateOfBirth); - command.Parameters.AddWithValue("@Email", email); - - await command.ExecuteNonQueryAsync(); - } - - 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 - ) - { - const string sql = """ -SELECT 1 -FROM dbo.UserVerification -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 AddUserVerificationAsync( - SqlConnection connection, - Guid userAccountId - ) - { - await using var command = new SqlCommand( - "dbo.USP_CreateUserVerification", - connection - ); - command.CommandType = CommandType.StoredProcedure; - command.Parameters.AddWithValue("@UserAccountID", userAccountId); - - await command.ExecuteNonQueryAsync(); - } - - private static string BuildUsername(string firstName, string lastName) - { - string username = $"{firstName}.{lastName}".ToLowerInvariant(); - return username.Length <= 64 ? username : username[..64]; - } - - private static string BuildEmail(string firstName, string lastName) - { - string email = $"{firstName}.{lastName}@example.com".ToLowerInvariant(); - return email.Length <= 128 ? email : email[..128]; - } - - private static DateTime GenerateDateOfBirth(Random random) - { - int age = 19 + random.Next(0, 30); - DateTime baseDate = DateTime.UtcNow.Date.AddYears(-age); - int offsetDays = random.Next(0, 365); - return baseDate.AddDays(-offsetDays); - } -} +} \ No newline at end of file diff --git a/DataAccessLayer/Entities/UserAccount.cs b/DataAccessLayer/Entities/UserAccount.cs index 2b93986..cf9baf5 100644 --- a/DataAccessLayer/Entities/UserAccount.cs +++ b/DataAccessLayer/Entities/UserAccount.cs @@ -2,7 +2,7 @@ namespace DataAccessLayer.Entities; public class UserAccount { - public Guid UserAccountID { get; set; } + public Guid UserAccountId { get; set; } public string Username { get; set; } = string.Empty; public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; diff --git a/DataAccessLayer/Entities/UserCredential.cs b/DataAccessLayer/Entities/UserCredential.cs index 3f4117a..07468ff 100644 --- a/DataAccessLayer/Entities/UserCredential.cs +++ b/DataAccessLayer/Entities/UserCredential.cs @@ -2,8 +2,8 @@ namespace DataAccessLayer.Entities; public class UserCredential { - public Guid UserCredentialID { get; set; } - public Guid UserAccountID { get; set; } + public Guid UserCredentialId { get; set; } + public Guid UserAccountId { get; set; } public DateTime CreatedAt { get; set; } public DateTime Expiry { get; set; } public string Hash { get; set; } = string.Empty; diff --git a/DataAccessLayer/Entities/UserVerification.cs b/DataAccessLayer/Entities/UserVerification.cs index 3eb0c13..6a503d8 100644 --- a/DataAccessLayer/Entities/UserVerification.cs +++ b/DataAccessLayer/Entities/UserVerification.cs @@ -2,8 +2,8 @@ namespace DataAccessLayer.Entities; public class UserVerification { - public Guid UserVerificationID { get; set; } - public Guid UserAccountID { get; set; } + public Guid UserVerificationId { get; set; } + public Guid UserAccountId { get; set; } public DateTime VerificationDateTime { get; set; } public byte[]? Timer { get; set; } } diff --git a/DataAccessLayer/IRepository.cs b/DataAccessLayer/Repositories/IRepository.cs similarity index 66% rename from DataAccessLayer/IRepository.cs rename to DataAccessLayer/Repositories/IRepository.cs index 5aee600..4b71078 100644 --- a/DataAccessLayer/IRepository.cs +++ b/DataAccessLayer/Repositories/IRepository.cs @@ -1,7 +1,8 @@ -using System; -using System.Collections.Generic; -namespace DataAccessLayer + +using Microsoft.Data.SqlClient; + +namespace DataAccessLayer.Repositories { public interface IRepository where T : class @@ -13,5 +14,7 @@ namespace DataAccessLayer T? GetById(Guid id); void Update(T entity); void Delete(Guid id); + + T MapToEntity(SqlDataReader entity); } } diff --git a/DataAccessLayer/Repositories/IUserAccountRepository.cs b/DataAccessLayer/Repositories/IUserAccountRepository.cs index 2e880a6..da1efbf 100644 --- a/DataAccessLayer/Repositories/IUserAccountRepository.cs +++ b/DataAccessLayer/Repositories/IUserAccountRepository.cs @@ -1,8 +1,6 @@ -using System; -using System.Collections.Generic; using DataAccessLayer.Entities; -namespace DataAccessLayer +namespace DataAccessLayer.Repositories { public interface IUserAccountRepository : IRepository { diff --git a/DataAccessLayer/Repositories/UserAccountRepository.cs b/DataAccessLayer/Repositories/UserAccountRepository.cs index 4790f3e..00103b0 100644 --- a/DataAccessLayer/Repositories/UserAccountRepository.cs +++ b/DataAccessLayer/Repositories/UserAccountRepository.cs @@ -1,30 +1,36 @@ -using System; -using System.Collections.Generic; using DataAccessLayer.Entities; using Microsoft.Data.SqlClient; -namespace DataAccessLayer +namespace DataAccessLayer.Repositories { public class UserAccountRepository : IUserAccountRepository { - private readonly string _connectionString; - - public UserAccountRepository() - { - // Retrieve the connection string from environment variables - _connectionString = - Environment.GetEnvironmentVariable("DB_CONNECTION_STRING") - ?? throw new InvalidOperationException( - "The connection string is not set in the environment variables." - ); - } + private readonly string _connectionString = Environment.GetEnvironmentVariable("DB_CONNECTION_STRING") + ?? throw new InvalidOperationException( + "The connection string is not set in the environment variables." + ); public void Add(UserAccount userAccount) { using SqlConnection connection = new(_connectionString); using SqlCommand command = new("usp_CreateUserAccount", connection); command.CommandType = System.Data.CommandType.StoredProcedure; - AddUserAccountCreateParameters(command, userAccount); + + command.Parameters.AddWithValue( + "@UserAccountId", + userAccount.UserAccountId + ); + command.Parameters.AddWithValue("@Username", userAccount.Username); + command.Parameters.AddWithValue( + "@FirstName", + userAccount.FirstName + ); + command.Parameters.AddWithValue("@LastName", userAccount.LastName); + command.Parameters.AddWithValue("@Email", userAccount.Email); + command.Parameters.AddWithValue( + "@DateOfBirth", + userAccount.DateOfBirth + ); connection.Open(); command.ExecuteNonQuery(); } @@ -41,7 +47,7 @@ namespace DataAccessLayer connection.Open(); using SqlDataReader reader = command.ExecuteReader(); - return reader.Read() ? MapUserAccount(reader) : null; + return reader.Read() ? MapToEntity(reader) : null; } public void Update(UserAccount userAccount) @@ -49,7 +55,25 @@ namespace DataAccessLayer using SqlConnection connection = new(_connectionString); using SqlCommand command = new("usp_UpdateUserAccount", connection); command.CommandType = System.Data.CommandType.StoredProcedure; - AddUserAccountUpdateParameters(command, userAccount); + command.Parameters.AddWithValue( + "@UserAccountId", + userAccount.UserAccountId + ); + command.Parameters.AddWithValue("@Username", userAccount.Username); + command.Parameters.AddWithValue( + "@FirstName", + userAccount.FirstName + ); + command.Parameters.AddWithValue("@LastName", userAccount.LastName); + command.Parameters.AddWithValue("@Email", userAccount.Email); + command.Parameters.AddWithValue( + "@DateOfBirth", + userAccount.DateOfBirth + ); + command.Parameters.AddWithValue( + "@UserAccountId", + userAccount.UserAccountId + ); connection.Open(); command.ExecuteNonQuery(); } @@ -64,9 +88,10 @@ namespace DataAccessLayer command.ExecuteNonQuery(); } + public IEnumerable GetAll(int? limit, int? offset) { - if (limit.HasValue && limit <= 0) + if (limit is <= 0) { throw new ArgumentOutOfRangeException( nameof(limit), @@ -110,7 +135,7 @@ namespace DataAccessLayer List users = new(); while (reader.Read()) { - users.Add(MapUserAccount(reader)); + users.Add(MapToEntity(reader)); } return users; @@ -127,8 +152,8 @@ namespace DataAccessLayer command.Parameters.AddWithValue("@Username", username); connection.Open(); - using SqlDataReader reader = command.ExecuteReader(); - return reader.Read() ? MapUserAccount(reader) : null; + using SqlDataReader? reader = command.ExecuteReader(); + return reader.Read() ? MapToEntity(reader) : null; } public UserAccount? GetByEmail(string email) @@ -143,48 +168,14 @@ namespace DataAccessLayer connection.Open(); using SqlDataReader reader = command.ExecuteReader(); - return reader.Read() ? MapUserAccount(reader) : null; + return reader.Read() ? MapToEntity(reader) : null; } - private static void AddUserAccountCreateParameters( - SqlCommand command, - UserAccount userAccount - ) - { - command.Parameters.AddWithValue( - "@UserAccountId", - userAccount.UserAccountID - ); - command.Parameters.AddWithValue("@Username", userAccount.Username); - command.Parameters.AddWithValue( - "@FirstName", - userAccount.FirstName - ); - command.Parameters.AddWithValue("@LastName", userAccount.LastName); - command.Parameters.AddWithValue("@Email", userAccount.Email); - command.Parameters.AddWithValue( - "@DateOfBirth", - userAccount.DateOfBirth - ); - } - - private static void AddUserAccountUpdateParameters( - SqlCommand command, - UserAccount userAccount - ) - { - AddUserAccountCreateParameters(command, userAccount); - command.Parameters.AddWithValue( - "@UserAccountId", - userAccount.UserAccountID - ); - } - - private static UserAccount MapUserAccount(SqlDataReader reader) + public UserAccount MapToEntity(SqlDataReader reader) { return new UserAccount { - UserAccountID = reader.GetGuid(0), + UserAccountId = reader.GetGuid(0), Username = reader.GetString(1), FirstName = reader.GetString(2), LastName = reader.GetString(3), diff --git a/DataAccessLayer/Sql/DatabaseHelper.cs b/DataAccessLayer/Sql/DatabaseHelper.cs index 53171a0..5096a13 100644 --- a/DataAccessLayer/Sql/DatabaseHelper.cs +++ b/DataAccessLayer/Sql/DatabaseHelper.cs @@ -4,45 +4,31 @@ using Microsoft.Data.SqlClient; namespace DataAccessLayer.Sql { - public class DatabaseHelper + public class DatabaseHelper(string connectionString) { - private readonly string _connectionString; - - public DatabaseHelper(string connectionString) - { - _connectionString = connectionString; - } - public void ExecuteRawSql(string query) { try { - using ( - SqlConnection connection = new SqlConnection( - _connectionString - ) - ) + using var connection = new SqlConnection( + connectionString + ); + + connection.Open(); + + using var command = new SqlCommand(query, connection); + + command.CommandType = CommandType.Text; + + using var reader = command.ExecuteReader(); + + while (reader.Read()) { - connection.Open(); - - using ( - SqlCommand command = new SqlCommand(query, connection) - ) + for (var i = 0; i < reader.FieldCount; i++) { - command.CommandType = CommandType.Text; - - using (SqlDataReader reader = command.ExecuteReader()) - { - while (reader.Read()) - { - for (int i = 0; i < reader.FieldCount; i++) - { - Console.WriteLine( - $"{reader.GetName(i)}: {reader.GetValue(i)}" - ); - } - } - } + Console.WriteLine( + $"{reader.GetName(i)}: {reader.GetValue(i)}" + ); } } } diff --git a/WebAPI/Controllers/UsersController.cs b/WebAPI/Controllers/UsersController.cs index 18c08b3..1764447 100644 --- a/WebAPI/Controllers/UsersController.cs +++ b/WebAPI/Controllers/UsersController.cs @@ -65,15 +65,15 @@ namespace WebAPI.Controllers [HttpPost] public IActionResult CreateUser([FromBody] UserAccount userAccount) { - if (userAccount.UserAccountID == Guid.Empty) + if (userAccount.UserAccountId == Guid.Empty) { - userAccount.UserAccountID = Guid.NewGuid(); + userAccount.UserAccountId = Guid.NewGuid(); } _userService.Add(userAccount); return CreatedAtAction( nameof(GetUserById), - new { id = userAccount.UserAccountID }, + new { id = userAccount.UserAccountId }, userAccount ); } @@ -85,14 +85,14 @@ namespace WebAPI.Controllers ) { if ( - userAccount.UserAccountID != Guid.Empty - && userAccount.UserAccountID != id + userAccount.UserAccountId != Guid.Empty + && userAccount.UserAccountId != id ) { return BadRequest("UserAccountID does not match route id."); } - userAccount.UserAccountID = id; + userAccount.UserAccountId = id; _userService.Update(userAccount); return NoContent(); } diff --git a/WebAPI/Program.cs b/WebAPI/Program.cs index 24618ed..9b595a0 100644 --- a/WebAPI/Program.cs +++ b/WebAPI/Program.cs @@ -1,5 +1,6 @@ using BusinessLayer.Services; using DataAccessLayer; +using DataAccessLayer.Repositories; var builder = WebApplication.CreateBuilder(args);