diff --git a/.gitignore b/.gitignore
index 7292219..fdd8cdc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,6 @@
/API/bin/
/API/obj/
/API/appsettings.*
+/Setup/bin/
+/Setup/obj/
+/Setup/appsettings.*
diff --git a/.idea/.idea.sanAntonioSeniorGolf/.idea/sqldialects.xml b/.idea/.idea.sanAntonioSeniorGolf/.idea/sqldialects.xml
new file mode 100644
index 0000000..245d345
--- /dev/null
+++ b/.idea/.idea.sanAntonioSeniorGolf/.idea/sqldialects.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Setup/Filler/Grants.sql b/Setup/Filler/Grants.sql
new file mode 100644
index 0000000..1c96164
--- /dev/null
+++ b/Setup/Filler/Grants.sql
@@ -0,0 +1,180 @@
+SET FOREIGN_KEY_CHECKS = 0;
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.color.get.all', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.color.get.any', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.color.get', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.color.add', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.color.update.any', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.color.update', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.color.delete.any', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.color.delete', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.event.get.all', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.event.get.any', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.event.get', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.event.add', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.event.update.any', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.event.update', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.event.delete.any', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.event.delete', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.grant.get.all', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.grant.get.any', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.grant.get', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.grant.add', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.grant.update.any', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.grant.update', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.grant.delete.any', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.grant.delete', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.image.get.all', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.image.get.any', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.image.get', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.image.add', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.image.update.any', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.image.update', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.image.delete.any', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.image.delete', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.permission.get.all', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.permission.get.any', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.permission.get', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.permission.add', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.permission.update.any', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.permission.update', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.permission.delete.any', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.permission.delete', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.savedEvent.get.all', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.savedEvent.get.any', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.savedEvent.get', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.savedEvent.add', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.savedEvent.update.any', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.savedEvent.update', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.savedEvent.delete.any', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.savedEvent.delete', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.user.get.all', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.user.get.any', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.user.get', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.user.add', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.user.update.any', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.user.update', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.user.update.self', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.user.update.names', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.user.update.phoneNumber', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.user.update.permission', 1, NOW(), 1);
+
+INSERT INTO san_antonio_senior_golf.grants (name, permissionId, updated, updater)
+VALUES ('api.user.delete.any', 1, NOW(), 1);
+
+SET FOREIGN_KEY_CHECKS = 1;
diff --git a/Setup/Filler/Permissions.sql b/Setup/Filler/Permissions.sql
new file mode 100644
index 0000000..7446a68
--- /dev/null
+++ b/Setup/Filler/Permissions.sql
@@ -0,0 +1,6 @@
+SET FOREIGN_KEY_CHECKS = 0;
+
+INSERT INTO san_antonio_senior_golf.permissions (name, updated, updater)
+VALUES ('admin', NOW(), 1);
+
+SET FOREIGN_KEY_CHECKS = 1;
diff --git a/Setup/Program.cs b/Setup/Program.cs
new file mode 100644
index 0000000..507eca2
--- /dev/null
+++ b/Setup/Program.cs
@@ -0,0 +1,116 @@
+using API.Hashing;
+using API.Hashing.Interfaces;
+using DAL.Contexts;
+using DAL.Models;
+using DAL.Values;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Options;
+using MySql.Data.MySqlClient;
+using Mysqlx.Session;
+using System.Configuration;
+using System.Data.Common;
+
+namespace Setup
+{
+ internal class Program
+ {
+ public static bool lineIsYes(string? input)
+ {
+ if (input == null)
+ return false;
+
+ input = input.Trim().ToLower();
+ switch (input)
+ {
+ case "y":
+ case "yes":
+ return true;
+ case "n":
+ case "no":
+ return false;
+ default:
+ return false;
+ }
+ }
+
+ public static string getStringWithConfirmation(string message)
+ {
+ while (true)
+ {
+ Console.Write(message);
+ string? input = Console.ReadLine();
+ Console.WriteLine();
+ if (input == null)
+ continue;
+
+ Console.Write($"Is '{input}' correct? [Y/N]: ");
+ if (lineIsYes(Console.ReadLine()))
+ {
+ Console.WriteLine();
+ return input;
+ }
+
+ Console.WriteLine();
+ }
+ }
+
+ public static void Main(string[] args)
+ {
+ Console.Write("Entering setup. Only run this once. Will reinstate database. Continue? [Y/N]: ");
+ if (!lineIsYes(Console.ReadLine()))
+ System.Environment.Exit(0);
+ Console.WriteLine();
+
+ string connectionString = getStringWithConfirmation("Enter connection string: ");
+
+ DbContextOptionsBuilder optionsBuilder = new DbContextOptionsBuilder();
+ optionsBuilder.UseMySQL(connectionString);
+
+ SASGContext context = new SASGContext(optionsBuilder.Options);
+
+ string firstName = getStringWithConfirmation("Enter admin first name: ");
+ string lastname = getStringWithConfirmation("Enter admin last name: ");
+ PhoneNumber phoneNumber = getStringWithConfirmation("Enter admin phone number: ");
+ string unHashedPassword = getStringWithConfirmation("Enter admin password: ");
+
+ HashingType defaultHashingType = Enum.Parse(
+ getStringWithConfirmation($"Enter default hashing type [{String.Join(", ", Enum.GetNames(typeof(HashingType)))}]: "));
+
+ IHashingFactory hashingFactory = new HashingFactory();
+ IHashingAlgorithm algorithm = hashingFactory.getAlgorithm(defaultHashingType) ?? throw new InvalidOperationException();
+
+ byte[] salt;
+ string password = algorithm.hash(unHashedPassword, out salt);
+
+ Console.Write("About to touch db. Continue? [Y/N]: ");
+ if (!lineIsYes(Console.ReadLine()))
+ System.Environment.Exit(0);
+
+ MySqlConnection conn = (MySqlConnection) context.Database.GetDbConnection();
+
+ conn.Open();
+ using (MySqlCommand reader = new MySqlCommand(File.ReadAllText("Filler/Permissions.sql"), conn))
+ {
+ reader.ExecuteNonQuery();
+ }
+
+ using (MySqlCommand reader = new MySqlCommand(File.ReadAllText("Filler/Grants.sql"), conn))
+ {
+ reader.ExecuteNonQuery();
+ }
+ conn.Close();
+
+ context.users.Add(new User
+ {
+ firstName = firstName,
+ lastName = lastname,
+ phoneNumber = phoneNumber,
+ password = password,
+ salt = salt,
+ hashingType = defaultHashingType,
+ permissionId = 1,
+ });
+ context.SaveChanges();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Setup/Setup.csproj b/Setup/Setup.csproj
new file mode 100644
index 0000000..16e4af6
--- /dev/null
+++ b/Setup/Setup.csproj
@@ -0,0 +1,26 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+
+ PreserveNewest
+
+
+
+
diff --git a/sanAntonioSeniorGolf.sln b/sanAntonioSeniorGolf.sln
index 2743f9f..b81bdc0 100644
--- a/sanAntonioSeniorGolf.sln
+++ b/sanAntonioSeniorGolf.sln
@@ -4,6 +4,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DAL", "DAL\DAL.csproj", "{E
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "API", "API\API.csproj", "{829DACCE-0D9E-43C8-A8C1-692C9FF6804A}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Setup", "Setup\Setup.csproj", "{B887051E-90C7-43BA-A08B-3958D570DCA7}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -18,5 +20,9 @@ Global
{829DACCE-0D9E-43C8-A8C1-692C9FF6804A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{829DACCE-0D9E-43C8-A8C1-692C9FF6804A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{829DACCE-0D9E-43C8-A8C1-692C9FF6804A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B887051E-90C7-43BA-A08B-3958D570DCA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B887051E-90C7-43BA-A08B-3958D570DCA7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B887051E-90C7-43BA-A08B-3958D570DCA7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B887051E-90C7-43BA-A08B-3958D570DCA7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal