diff --git a/server/AyaNova/Controllers/GlobalOpsSettingsController.cs b/server/AyaNova/Controllers/GlobalOpsSettingsController.cs index 7d409bad..1d6724f6 100644 --- a/server/AyaNova/Controllers/GlobalOpsSettingsController.cs +++ b/server/AyaNova/Controllers/GlobalOpsSettingsController.cs @@ -13,13 +13,13 @@ namespace AyaNova.Api.Controllers [ApiController] [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/global-ops-setting")] + [Route("api/v{version:apiVersion}/global-ops-backup-setting")] [Produces("application/json")] [Authorize] - public class GlobalOpsSettingsController : ControllerBase + public class GlobalOpsBackupSettingsController : ControllerBase { private readonly AyContext ct; - private readonly ILogger log; + private readonly ILogger log; private readonly ApiServerState serverState; @@ -30,7 +30,7 @@ namespace AyaNova.Api.Controllers /// /// /// - public GlobalOpsSettingsController(AyContext dbcontext, ILogger logger, ApiServerState apiServerState) + public GlobalOpsBackupSettingsController(AyContext dbcontext, ILogger logger, ApiServerState apiServerState) { ct = dbcontext; log = logger; @@ -48,7 +48,7 @@ namespace AyaNova.Api.Controllers return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); //Instantiate the business object handler - GlobalOpsSettingsBiz biz = GlobalOpsSettingsBiz.GetBiz(ct, HttpContext); + GlobalOpsBackupSettingsBiz biz = GlobalOpsBackupSettingsBiz.GetBiz(ct, HttpContext); if (!Authorized.HasReadFullRole(HttpContext.Items, biz.BizType)) return StatusCode(403, new ApiNotAuthorizedResponse()); @@ -70,13 +70,13 @@ namespace AyaNova.Api.Controllers /// /// nothing [HttpPost] - public async Task ReplaceGlobalOpsSettings([FromBody] GlobalOpsSettings global) + public async Task ReplaceGlobalOpsSettings([FromBody] GlobalOpsBackupSettings global) { if (serverState.IsClosed) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); if (!ModelState.IsValid) return BadRequest(new ApiErrorResponse(ModelState)); - GlobalOpsSettingsBiz biz = GlobalOpsSettingsBiz.GetBiz(ct, HttpContext); + GlobalOpsBackupSettingsBiz biz = GlobalOpsBackupSettingsBiz.GetBiz(ct, HttpContext); if (!Authorized.HasModifyRole(HttpContext.Items, biz.BizType)) return StatusCode(403, new ApiNotAuthorizedResponse()); try @@ -104,7 +104,7 @@ namespace AyaNova.Api.Controllers if (serverState.IsClosed) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); - GlobalOpsSettingsBiz biz = GlobalOpsSettingsBiz.GetBiz(ct, HttpContext); + GlobalOpsBackupSettingsBiz biz = GlobalOpsBackupSettingsBiz.GetBiz(ct, HttpContext); //this route is available to Ops role user only if (!Authorized.HasReadFullRole(HttpContext.Items, biz.BizType)) return StatusCode(403, new ApiNotAuthorizedResponse()); diff --git a/server/AyaNova/Startup.cs b/server/AyaNova/Startup.cs index 8e137a57..5471d58d 100644 --- a/server/AyaNova/Startup.cs +++ b/server/AyaNova/Startup.cs @@ -490,7 +490,7 @@ namespace AyaNova ServerGlobalBizSettings.Initialize(null, dbContext); _newLog.LogDebug("Ops settings"); - ServerGlobalOpsSettings.Initialize(null, dbContext); + ServerGlobalOpsSettingsCache.Initialize(dbContext); //Ensure translations are present, not missing any keys and that there is a server default translation that exists TranslationBiz lb = new TranslationBiz(dbContext, 1, ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID, AuthorizationRoles.OpsAdminFull); diff --git a/server/AyaNova/biz/GlobalOpsSettingsBiz.cs b/server/AyaNova/biz/GlobalOpsSettingsBiz.cs index a5515b83..2be03a4a 100644 --- a/server/AyaNova/biz/GlobalOpsSettingsBiz.cs +++ b/server/AyaNova/biz/GlobalOpsSettingsBiz.cs @@ -8,10 +8,10 @@ using AyaNova.Models; namespace AyaNova.Biz { - internal class GlobalOpsSettingsBiz : BizObject + internal class GlobalOpsBackupSettingsBiz : BizObject { - internal GlobalOpsSettingsBiz(AyContext dbcontext, long currentUserId, long userTranslationId, AuthorizationRoles UserRoles) + internal GlobalOpsBackupSettingsBiz(AyContext dbcontext, long currentUserId, long userTranslationId, AuthorizationRoles UserRoles) { ct = dbcontext; UserId = currentUserId; @@ -20,12 +20,12 @@ namespace AyaNova.Biz BizType = AyaType.GlobalOps; } - internal static GlobalOpsSettingsBiz GetBiz(AyContext ct, Microsoft.AspNetCore.Http.HttpContext httpContext = null) + internal static GlobalOpsBackupSettingsBiz GetBiz(AyContext ct, Microsoft.AspNetCore.Http.HttpContext httpContext = null) { if (httpContext != null) - return new GlobalOpsSettingsBiz(ct, UserIdFromContext.Id(httpContext.Items), UserTranslationIdFromContext.Id(httpContext.Items), UserRolesFromContext.Roles(httpContext.Items)); + return new GlobalOpsBackupSettingsBiz(ct, UserIdFromContext.Id(httpContext.Items), UserTranslationIdFromContext.Id(httpContext.Items), UserRolesFromContext.Roles(httpContext.Items)); else - return new GlobalOpsSettingsBiz(ct, 1, ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID, AuthorizationRoles.BizAdminFull); + return new GlobalOpsBackupSettingsBiz(ct, 1, ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID, AuthorizationRoles.BizAdminFull); } @@ -35,7 +35,7 @@ namespace AyaNova.Biz /// GET //Get one - internal async Task GetAsync(bool logTheGetEvent = true) + internal async Task GetAsync(bool logTheGetEvent = true) { //first try to fetch from db var ret = await ct.GlobalOpsSettings.SingleOrDefaultAsync(m => m.Id == 1); @@ -58,7 +58,7 @@ namespace AyaNova.Biz // //put - internal async Task ReplaceAsync(GlobalOpsSettings putObject) + internal async Task ReplaceAsync(GlobalOpsBackupSettings putObject) { var dbObject = await ct.GlobalOpsSettings.FirstOrDefaultAsync(m => m.Id == 1); if (dbObject == null) @@ -77,7 +77,7 @@ namespace AyaNova.Biz await ct.SaveChangesAsync(); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, 1, BizType, AyaEvent.Modified), ct); //Update the static copy for the server - ServerGlobalOpsSettings.Initialize(dbObject); + ServerGlobalOpsSettingsCache.Backup=dbObject; return true; } @@ -88,7 +88,7 @@ namespace AyaNova.Biz // //Can save or update? - private void Validate(GlobalOpsSettings inObj) + private void Validate(GlobalOpsBackupSettings inObj) { //currently nothing to validate diff --git a/server/AyaNova/generator/CoreJobBackup.cs b/server/AyaNova/generator/CoreJobBackup.cs index c9676e41..506c6484 100644 --- a/server/AyaNova/generator/CoreJobBackup.cs +++ b/server/AyaNova/generator/CoreJobBackup.cs @@ -32,7 +32,7 @@ namespace AyaNova.Biz log.LogTrace("Checking if backup should run"); //what time should we backup today? - DateTime todayBackupTime = new DateTime(utcNow.Year, utcNow.Month, utcNow.Day, ServerGlobalOpsSettings.BackupTime.Hour, ServerGlobalOpsSettings.BackupTime.Minute, 0, DateTimeKind.Utc);//first start with NOW + DateTime todayBackupTime = new DateTime(utcNow.Year, utcNow.Month, utcNow.Day, ServerGlobalOpsSettingsCache.Backup.BackupTime.Hour, ServerGlobalOpsSettingsCache.Backup.BackupTime.Minute, 0, DateTimeKind.Utc);//first start with NOW //Are we there yet? if (utcNow < todayBackupTime) { @@ -41,7 +41,7 @@ namespace AyaNova.Biz //Yes, we've passed into the backup window time, but that's also true if we just ran the backup as well so //need to check for that as well... //Has last backup run more than 24 hours ago? - if (ServerGlobalOpsSettings.LastBackup > utcNow.AddHours(-24)) + if (ServerGlobalOpsSettingsCache.Backup.LastBackup > utcNow.AddHours(-24)) { log.LogTrace("Hasn't been 24 hours since last backup yet"); return;//nope//nope, so we have already run today's backup } @@ -84,15 +84,15 @@ namespace AyaNova.Biz //PRUNE DATA BACKUP SETS NOT KEPT - FileUtil.DatabaseBackupCleanUp(ServerGlobalOpsSettings.BackupSetsToKeep); + FileUtil.DatabaseBackupCleanUp(ServerGlobalOpsSettingsCache.Backup.BackupSetsToKeep); //DO FILE BACKUP IF ATTACHMENTS BACKED UP - if (ServerGlobalOpsSettings.BackupAttachments) + if (ServerGlobalOpsSettingsCache.Backup.BackupAttachments) FileUtil.BackupAttachments(); //PRUNE DATA BACKUP SETS NOT KEPT - FileUtil.AttachmentBackupCleanUp(ServerGlobalOpsSettings.BackupSetsToKeep); + FileUtil.AttachmentBackupCleanUp(ServerGlobalOpsSettingsCache.Backup.BackupSetsToKeep); @@ -102,7 +102,7 @@ namespace AyaNova.Biz if (!OnDemand) { //Update last backup - var biz = GlobalOpsSettingsBiz.GetBiz(ct); + var biz = GlobalOpsBackupSettingsBiz.GetBiz(ct); var OpSet = await biz.GetAsync(false); OpSet.LastBackup = utcNow; await biz.ReplaceAsync(OpSet); diff --git a/server/AyaNova/models/AyContext.cs b/server/AyaNova/models/AyContext.cs index 0dc59561..4965d542 100644 --- a/server/AyaNova/models/AyContext.cs +++ b/server/AyaNova/models/AyContext.cs @@ -9,7 +9,7 @@ namespace AyaNova.Models public virtual DbSet UserOptions { get; set; } public virtual DbSet Widget { get; set; } public virtual DbSet GlobalBizSettings { get; set; } - public virtual DbSet GlobalOpsSettings { get; set; } + public virtual DbSet GlobalOpsSettings { get; set; } public virtual DbSet Event { get; set; } public virtual DbSet SearchDictionary { get; set; } public virtual DbSet SearchKey { get; set; } diff --git a/server/AyaNova/models/GlobalOpsBackupSettings.cs b/server/AyaNova/models/GlobalOpsBackupSettings.cs new file mode 100644 index 00000000..39cf677c --- /dev/null +++ b/server/AyaNova/models/GlobalOpsBackupSettings.cs @@ -0,0 +1,24 @@ +using System; +namespace AyaNova.Models +{ + + public class GlobalOpsBackupSettings + { + public long Id { get; set; }//this is always 1 as there is only ever one single global Ops object + public uint Concurrency { get; set; } + + public DateTime BackupTime { get; set; } + public DateTime LastBackup { get; set; } + public int BackupSetsToKeep { get; set; } + public bool BackupAttachments { get; set; } + + public GlobalOpsBackupSettings() + { + Id = 1;//always 1 + BackupTime = new DateTime(2020, 5, 19, 23, 59, 0, DateTimeKind.Utc);//date doesn't matter it only uses hour + LastBackup = DateTime.MinValue; + BackupSetsToKeep = 3; + + } + } +} diff --git a/server/AyaNova/util/AySchema.cs b/server/AyaNova/util/AySchema.cs index 17b0ef5b..13f29068 100644 --- a/server/AyaNova/util/AySchema.cs +++ b/server/AyaNova/util/AySchema.cs @@ -228,8 +228,8 @@ FROM index_groups; await ExecQueryAsync("CREATE TABLE aglobalbizsettings (id integer NOT NULL PRIMARY KEY, " + "searchcasesensitiveonly bool default false)"); - //create global ops settings table - await ExecQueryAsync("CREATE TABLE aglobalopssettings (id integer NOT NULL PRIMARY KEY, " + + //create global ops BACKUP settings table + await ExecQueryAsync("CREATE TABLE aglobalopsbackupsettings (id integer NOT NULL PRIMARY KEY, " + "backuptime timestamp, lastbackup timestamp, backupsetstokeep int, backupattachments bool)"); //create aevent biz event log table diff --git a/server/AyaNova/util/ServerGlobalOpsSettings.cs b/server/AyaNova/util/ServerGlobalOpsSettings.cs deleted file mode 100644 index cf9ed118..00000000 --- a/server/AyaNova/util/ServerGlobalOpsSettings.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -using System.Linq; -using AyaNova.Models; - -namespace AyaNova.Util -{ - - /// - /// Contains static mirror copy in memory of global settings values that are set from DB during boot - /// and accessible to Biz admin user (equivalent of v7's global object) - /// used by many areas of the biz logic and processing too often to fetch on every request - /// set at boot and on any update to the db global biz settings record - /// - internal static class ServerGlobalOpsSettings - { - - internal static DateTime BackupTime { get; set; } - internal static DateTime LastBackup { get; set; } - internal static int BackupSetsToKeep { get; set; } - internal static bool BackupAttachments { get; set; } - - /// - /// Populate and / or create the settings - /// - internal static void Initialize(GlobalOpsSettings global, AyContext ct = null) - { - - if (global == null) - { - //fetch or create as not provided (meaning this was called from Startup.cs) - global = ct.GlobalOpsSettings.FirstOrDefault(z => z.Id == 1); - if (global == null) - { - global = new GlobalOpsSettings(); - ct.GlobalOpsSettings.Add(global); - ct.SaveChanges(); - } - } - - //We have the object, now copy the static values here - BackupAttachments = global.BackupAttachments; - BackupSetsToKeep = global.BackupSetsToKeep; - BackupTime = global.BackupTime; - LastBackup = global.LastBackup; - } - - - - }//eoc -}//eons \ No newline at end of file diff --git a/server/AyaNova/util/ServerGlobalOpsSettingsCache.cs b/server/AyaNova/util/ServerGlobalOpsSettingsCache.cs new file mode 100644 index 00000000..9b84fd8e --- /dev/null +++ b/server/AyaNova/util/ServerGlobalOpsSettingsCache.cs @@ -0,0 +1,36 @@ +using System; +using System.Linq; +using AyaNova.Models; + +namespace AyaNova.Util +{ + + /// + /// Contains static mirror copy in memory of Operations related settings stored in db + /// that are accessed frequently by server + /// + internal static class ServerGlobalOpsSettingsCache + { + + internal static GlobalOpsBackupSettings Backup { get; set; } + + + /// + /// Populate and / or create the settings + /// + internal static void Initialize(AyContext ct = null) + { + //fetch or create as not provided (meaning this was called from Startup.cs) + Backup = ct.GlobalOpsSettings.FirstOrDefault(z => z.Id == 1); + if (Backup == null) + { + Backup = new GlobalOpsBackupSettings(); + ct.GlobalOpsSettings.Add(Backup); + ct.SaveChanges(); + } + } + + + + }//eoc +}//eons \ No newline at end of file