TireTargetsWeb/Components/CSharp/DatabaseDriver.cs

278 lines
10 KiB
C#

using Microsoft.Data.SqlClient;
using System.Collections.Concurrent;
using System.Data;
using System.Threading.Tasks;
using Telerik.Windows.Documents.Fixed.Model.Editing.Lists;
using Telerik.Windows.Documents.Fixed.Model.Navigation;
using XAct;
namespace TireTargets.Components.CSharp
{
public class DatabaseDriver : IDisposable
{
private bool disposedValue;
private ConcurrentBag<System.Threading.Tasks.Task> _tasks = new ConcurrentBag<System.Threading.Tasks.Task>();
private bool isExiting = false;
private static string _connectionString = "Server=BigMac; Database=TireTargets; Integrated Security=SSPI;MultipleActiveResultSets=True;TrustServerCertificate=True;";
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
isExiting = true;
Task.WaitAll(_tasks.ToArray());
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
public static async Task<bool> SignIn(string platform, string id, string fname, string email)
{
try
{
using (var cn = new SqlConnection(_connectionString))
{
await cn.OpenAsync();
await using var queryCmd = new SqlCommand(String.Format("SELECT COUNT(UniqID) FROM [dbo].[User] WHERE {0}ID = '{1}'", platform, id), cn);
await using var rd = await queryCmd.ExecuteReaderAsync();
// Get number of occurences of this ID/Platform combo
int count = -1;
while (await rd.ReadAsync())
{
count = rd.GetInt32(0);
}
if (count > 0) // If the account already exists, read from the DB for session info
{
}
else // Otherwise, we need to create a new account
{
await using var insertCmd = new SqlCommand(String.Format("INSERT INTO [dbo].[User] ({0}ID, {0}Name, {0}Email) VALUES (@id, @fname, @email)", platform), cn);
insertCmd.Parameters.AddWithValue("@id", id);
insertCmd.Parameters.AddWithValue("@fname", fname);
insertCmd.Parameters.AddWithValue("@email", email);
insertCmd.ExecuteNonQuery();
}
cn.Close();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return false;
}
return true;
}
public static async Task<List<Location>> GetLocationInfoForUser(string id, string platform)
{
try
{
using (var cn = new SqlConnection(_connectionString))
{
await cn.OpenAsync();
// Confirm that user has a valid location ID set
string locQueryString = "";
if (platform == "Google")
locQueryString = String.Format("SELECT [LocationID] FROM [dbo].[User] WHERE [GoogleID] = '{0}'", id.Replace("'","''"));
else if (platform == "FB")
locQueryString = String.Format("SELECT [LocationID] FROM [dbo].[User] WHERE [FBID] = '{0}'", id.Replace("'", "''"));
await using var locQuery = new SqlCommand(locQueryString, cn);
await using var locRd = await locQuery.ExecuteReaderAsync();
// Extract loc id
int locationId = -1;
while (await locRd.ReadAsync())
{
locationId = locRd.GetInt32(0);
}
// Check if user's LocID is a RootID
string rootString = String.Format("SELECT COUNT(*) FROM [dbo].[Location] WHERE RootID = {0}", ("" + locationId).Replace("'","''"));
SqlCommand cmd = new SqlCommand(rootString, cn);
Int32 val = (Int32)cmd.ExecuteScalar();
string locInfoString = "";
if (val > 1)
{
locInfoString = String.Format("SELECT * FROM [dbo].[Location] WHERE RootID = {0}", ("" + locationId).Replace("'", "''"));
}
else // Nothing matches
{
locInfoString = String.Format("SELECT * FROM [dbo].[Location] WHERE LocationID = {0}", ("" + locationId).Replace("'", "''"));
}
// Find the location in Location table
await using var queryCmd = new SqlCommand(locInfoString, cn);
await using var rd = await queryCmd.ExecuteReaderAsync();
// Extract loc id
List<Location> locations = new List<Location>();
while (await rd.ReadAsync())
{
var locID = rd.GetInt32(0);
var rootID = rd.GetInt32(1);
var locName = rd.GetString(2);
var lastSelected = rd.GetDateTime(3);
var needSelection = rd.GetInt32(4);
var selectionJson = rd.GetString(5);
var enabled = rd.GetInt32(6);
Location current = new Location(locID, rootID, locName, lastSelected, needSelection, selectionJson, enabled);
locations.Add(current);
}
cn.Close();
return locations;
}
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
}
return new List<Location>();
}
public static async Task<(DateTime, DateTime)> GetSelectionTimes()
{
using (var cn = new SqlConnection(_connectionString))
{
await cn.OpenAsync();
await using var cmd = new SqlCommand("SELECT * FROM [cfg].[Selection]", cn);
await using var rd = await cmd.ExecuteReaderAsync();
(DateTime, DateTime) selectionTime = (default, default);
while (await rd.ReadAsync())
{
selectionTime.Item1 = rd.GetDateTime(0);
selectionTime.Item2 = rd.GetDateTime(1);
}
return selectionTime;
}
}
public static async Task<List<(int,bool)>> DoesLocationNeedSelection()
{
// Determine if offers need to be selected
var locInfo = await GetLocationInfoForUser(Layout.MainLayout.Session["id"], Layout.MainLayout.Session["login_method"]);
var selectionTime = await GetSelectionTimes();
List<(int, bool)> results = new List<(int, bool)> ();
foreach (Location current in locInfo)
{
// Location NeedSelection is effectively an override, forcing them to re-select for the flagged location(s)
if (current.NeedSelection == 1 || (current.LastSelected < selectionTime.Item1 && DateTime.Now < selectionTime.Item2))
{
results.Add((current.LocationID, true));
}
else
{
results.Add((current.LocationID, false));
}
}
return results;
}
public static async Task<bool> DoesUserHaveLocation(string id, string platform)
{
using (var cn = new SqlConnection(_connectionString))
{
await cn.OpenAsync();
string queryString = "";
if (platform == "Google")
queryString = String.Format("SELECT [LocationID] FROM [dbo].[User] WHERE [GoogleID] = '{0}'", id.Replace("'", "''"));
else if (platform == "FB")
queryString = String.Format("SELECT [LocationID] FROM [dbo].[User] WHERE [FBID] = '{0}'", id.Replace("'", "''"));
await using var cmd = new SqlCommand(queryString, cn);
await using var rd = await cmd.ExecuteReaderAsync();
while (await rd.ReadAsync())
{
if (rd.IsDBNull(0) || rd.GetInt32(0) == -1)
return false;
}
return true;
}
}
public static async Task<bool> UpdateSelection(Dictionary<int, string> locSelections)
{
using (var cn = new SqlConnection(_connectionString))
{
await cn.OpenAsync();
foreach (var current in locSelections)
{
var query = String.Format("UPDATE [dbo].[Location] SET [SelectionJson] = '{0}', [LastSelected] = GETDATE() WHERE LocationID = {1}", current.Value, current.Key);
await using var cmd = new SqlCommand(query, cn);
cmd.ExecuteNonQuery();
}
}
return true;
}
public class Location
{
public Location(int locID, int rootID, string locName, DateTime lastSelect, int needSelection, string selectionJson, int enabled)
{
LocationID = locID;
RootID = rootID;
LocationName = locName;
LastSelected = lastSelect;
NeedSelection = needSelection;
SelectionJson = selectionJson;
Enabled = enabled;
}
public int LocationID { get; set; }
public int RootID { get; set; }
public string LocationName { get; set; }
public DateTime LastSelected { get; set; }
public int NeedSelection { get; set; }
public string SelectionJson { get; set; }
public int Enabled { get; set; }
}
}
}