using System.Diagnostics.CodeAnalysis; using InnovEnergy.App.Backend.Model; using InnovEnergy.App.Backend.Model.Relations; using InnovEnergy.App.Backend.Utils; using InnovEnergy.Lib.Utils; using SQLite; namespace InnovEnergy.App.Backend.Database; public partial class Db : IDisposable { internal const String DbPath = "./db.sqlite"; private readonly SQLiteConnection _Db; // internal handle to the connection, disposable private TableQuery Sessions => _Db.Table(); [SuppressMessage("ReSharper", "AccessToDisposedClosure")] static Db() { // on startup create/migrate tables using var db = new SQLiteConnection(DbPath); db.RunInTransaction(() => { db.CreateTable(); db.CreateTable(); db.CreateTable(); db.CreateTable(); db.CreateTable(); db.CreateTable(); }); } // private, force access through Connect() private Db() => _Db = new SQLiteConnection(DbPath); public static Db Connect() => new Db(); public void Dispose() => _Db.Dispose(); // the C in CRUD private Result Create(TreeNode treeNode) { try { _Db.Insert(treeNode); } catch (Exception e) { return Result.Error(e); } return Result.Ok; } // the U in CRUD private Result Update(TreeNode treeNode) { try { _Db.InsertOrReplace(treeNode); } catch (Exception e) { return Result.Error(e); } return Result.Ok; } // the D in CRUD private Result Delete(TreeNode treeNode) { try { _Db.Delete(treeNode); } catch (Exception e) { return Result.Error(e); } return Result.Ok; } public IEnumerable GetAllAccessibleInstallations(User user) { var direct = GetDirectlyAccessibleInstallations(user); var fromFolders = GetAllAccessibleFolders(user) .SelectMany(GetChildInstallations); return direct .Concat(fromFolders) .Distinct(); } public IEnumerable GetAllAccessibleFolders(User user) { return GetDirectlyAccessibleFolders(user) .SelectMany(GetDescendantFolders) .Distinct(); // Distinct because the user might have direct access // to a child folder of a folder he has already access to } public IEnumerable GetDirectlyAccessibleInstallations(User user) { return User2Installation .Where(r => r.UserId == user.Id) .Select(r => r.InstallationId) .Select(GetInstallationById) .NotNull() .Do(i => i.ParentId = 0); // hide inaccessible parents from calling user } public IEnumerable GetDirectlyAccessibleFolders(User user) { return User2Folder .Where(r => r.UserId == user.Id) .Select(r => r.FolderId) .Select(GetFolderById) .NotNull() .Do(i => i.ParentId = 0); // hide inaccessible parents from calling user; } public Result AddToAccessibleInstallations(Int64 userId, Int64 updatedInstallationId) { var con = new User2Installation { UserId = userId, InstallationId = updatedInstallationId }; try { _Db.InsertOrReplace(con); } catch (Exception e) { return Result.Error(e); } return Result.Ok; } public Result AddToAccessibleFolders(Int64 userId, Int64 updatedFolderId) { var con = new User2Folder { UserId = userId, FolderId = updatedFolderId }; try { _Db.InsertOrReplace(con); } catch (Exception e) { return Result.Error(e); } return Result.Ok; } public User? GetUserByToken(String token) { return Sessions .Where(s => s.Token == token).ToList() .Where(s => s.Valid) .Select(s => s.UserId) .Select(GetUserById) .FirstOrDefault(); } public Result NewSession(Session ses) { try { _Db.InsertOrReplace(ses); } catch (Exception e) { return Result.Error(e); } return Result.Ok; } public Result DeleteSession(Int64 id) { try { Sessions.Delete(u => u.UserId == id); } catch (Exception e) { return Result.Error(e); } return Result.Ok; } public Object? GetInstallationS3Key(Int64 installationId) { return Installations .Where(installation => installation.Id == installationId) .Select(installation => installation.S3Key); } public void DeleteS3KeysDaily() { foreach (var installation in Installations.ToList()) { installation.S3Key = null; Update(installation); } } }