using System.Reactive.Concurrency; using System.Reactive.Linq; using CliWrap; using CliWrap.Buffered; using InnovEnergy.App.Backend.DataTypes; using InnovEnergy.App.Backend.DataTypes.Methods; using InnovEnergy.App.Backend.Relations; using InnovEnergy.Lib.S3Utils; using InnovEnergy.Lib.S3Utils.DataTypes; using SQLite; using SQLiteConnection = SQLite.SQLiteConnection; namespace InnovEnergy.App.Backend.Database; public static partial class Db { // internal const String DbPath = "./db.sqlite"; private static SQLiteConnection Connection { get; } = ((Func)(() => { var latestDb = new DirectoryInfo(@"DbBackups").GetFiles() .OrderBy(f => f.LastWriteTime) .Last().Name; var fileConnection = new SQLiteConnection("DbBackups/"+latestDb); Console.Out.Write(latestDb); var memoryConnection = new SQLiteConnection(":memory:"); // fileConnection.Backup(memoryConnection.DatabasePath); memoryConnection.CreateTable(); memoryConnection.CreateTable(); memoryConnection.CreateTable(); memoryConnection.CreateTable(); memoryConnection.CreateTable(); memoryConnection.CreateTable(); memoryConnection.CreateTable(); foreach (var obj in fileConnection.Table()) { memoryConnection.Insert(obj); } foreach (var obj in fileConnection.Table()) { memoryConnection.Insert(obj); } foreach (var obj in fileConnection.Table()) { memoryConnection.Insert(obj); } foreach (var obj in fileConnection.Table()) { memoryConnection.Insert(obj); } foreach (var obj in fileConnection.Table()) { memoryConnection.Insert(obj); } foreach (var obj in fileConnection.Table()) { memoryConnection.Insert(obj); } foreach (var obj in fileConnection.Table()) { memoryConnection.Insert(obj); } return memoryConnection; }))(); public static void BackupDatabase() { var filename = "db-" + DateTimeOffset.UtcNow.ToUnixTimeSeconds() + ".sqlite"; Connection.Backup("DbBackups/" + filename); } public static TableQuery Sessions => Connection.Table(); public static TableQuery Folders => Connection.Table(); public static TableQuery Installations => Connection.Table(); public static TableQuery Users => Connection.Table(); public static TableQuery FolderAccess => Connection.Table(); public static TableQuery InstallationAccess => Connection.Table(); public static TableQuery OrderNumber2Installation => Connection.Table(); public static void Init() { // used to force static constructor } static Db() { // on startup create/migrate tables Connection.RunInTransaction(() => { Connection.CreateTable(); Connection.CreateTable(); Connection.CreateTable(); Connection.CreateTable(); Connection.CreateTable(); Connection.CreateTable(); Connection.CreateTable(); }); Observable.Interval(TimeSpan.FromHours(0.5)) .StartWith(0) // Do it right away (on startup) .ObserveOn(TaskPoolScheduler.Default) .SubscribeOn(TaskPoolScheduler.Default) .SelectMany(Cleanup) .Subscribe(); } private static Boolean RunTransaction(Func func) { var savepoint = Connection.SaveTransactionPoint(); var success = false; try { success = func(); } finally { if (success) Connection.Release(savepoint); else Connection.RollbackTo(savepoint); } return success; } private static async Task Cleanup(Int64 _) { await UpdateS3Urls(); DeleteStaleSessions(); return true; } private static void DeleteStaleSessions() { var deadline = DateTime.Now.AddDays((-1)*Session.MaxAge.Days); Sessions.Delete(s => s.LastSeen < deadline); } private static async Task UpdateS3Urls() { var regions = Installations .Select(i => i.S3Region) .Distinct().ToList(); const String provider = "exo.io"; foreach (var region in regions) { var bucketList = await new S3Region($"https://{region}.{provider}", ExoCmd.S3Creds!).ListAllBuckets(); foreach (var bucket in bucketList.Buckets) { foreach (var installation in Installations) { if (installation.BucketName() == bucket.BucketName) { await installation.RenewS3Credentials(); } } } } } public static Boolean SendPasswordResetEmail(User user, String sessionToken) { return Email.Email.SendPasswordResetMessage(user, sessionToken); } public static Boolean SendNewUserEmail(User user) { return Email.Email.SendNewUserMessage(user); } public static Boolean DeleteUserPassword(User user) { user.Password = ""; user.MustResetPassword = true; return Update(user); } }