From e2688e6febb18238e4ee8c4e504ea9e0058b69cc Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Fri, 7 Jan 2022 23:30:29 -0500 Subject: [PATCH] include purge job for maintaining event logs and visitor logs --- Oqtane.Client/Modules/Admin/Logs/Index.razor | 157 +++++---- .../Modules/Admin/Visitors/Index.razor | 37 ++- .../Resources/Modules/Admin/Logs/Index.resx | 18 ++ .../Modules/Admin/Visitors/Index.resx | 18 +- .../Themes/Controls/Theme/ControlPanel.razor | 301 +++++++++--------- Oqtane.Server/Infrastructure/Jobs/PurgeJob.cs | 76 +++++ Oqtane.Server/Pages/_Host.cshtml.cs | 18 +- .../Repository/Interfaces/ILogRepository.cs | 3 +- .../Interfaces/ISettingRepository.cs | 1 + .../Interfaces/IVisitorRepository.cs | 1 + Oqtane.Server/Repository/LogRepository.cs | 21 +- Oqtane.Server/Repository/SettingRepository.cs | 12 + Oqtane.Server/Repository/VisitorRepository.cs | 18 ++ 13 files changed, 458 insertions(+), 223 deletions(-) create mode 100644 Oqtane.Server/Infrastructure/Jobs/PurgeJob.cs diff --git a/Oqtane.Client/Modules/Admin/Logs/Index.razor b/Oqtane.Client/Modules/Admin/Logs/Index.razor index c9818389..7a30893d 100644 --- a/Oqtane.Client/Modules/Admin/Logs/Index.razor +++ b/Oqtane.Client/Modules/Admin/Logs/Index.razor @@ -1,6 +1,7 @@ @namespace Oqtane.Modules.Admin.Logs @inherits ModuleBase @inject ILogService LogService +@inject ISettingService SettingService @inject IStringLocalizer Localizer @inject IStringLocalizer SharedLocalizer @@ -10,67 +11,83 @@ } else { -
-
-
-

- -
-
-

- -
-
-

- -
-
-
-
+ + +
+
+
+

+ +
+
+

+ +
+
+

+ +
+
+
+
- @if (_logs.Any()) - { - -
-   - @Localizer["Date"] - @Localizer["Level"] - @Localizer["Feature"] - @Localizer["Function"] -
- - - @context.LogDate - @context.Level - @context.Feature - @context.Function - -
- } - else - { -

@Localizer["NoLogs"]

- } + @if (_logs.Any()) + { + +
+   + @Localizer["Date"] + @Localizer["Level"] + @Localizer["Feature"] + @Localizer["Function"] +
+ + + @context.LogDate + @context.Level + @context.Feature + @context.Function + +
+ } + else + { +

@Localizer["NoLogs"]

+ } +
+ +
+
+ +
+ +
+
+
+
+ +
+
} @code { @@ -78,6 +95,7 @@ else private string _function = "-"; private string _rows = "10"; private List _logs; + private string _retention = ""; public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host; @@ -86,6 +104,7 @@ else try { await GetLogs(); + _retention = SettingService.GetSetting(PageState.Site.Settings, "LogRetention", "30"); } catch (Exception ex) { @@ -171,4 +190,22 @@ else } return classname; } + + private async Task SaveSiteSettings() + { + try + { + var settings = PageState.Site.Settings; + settings = SettingService.SetSetting(settings, "LogRetention", _retention); + await SettingService.UpdateSiteSettingsAsync(settings, PageState.Site.SiteId); + + AddModuleMessage(Localizer["Success.SaveSiteSettings"], MessageType.Success); + } + catch (Exception ex) + { + await logger.LogError(ex, "Error Saving Site Settings {Error}", ex.Message); + AddModuleMessage(Localizer["Error.SaveSiteSettings"], MessageType.Error); + } + } + } diff --git a/Oqtane.Client/Modules/Admin/Visitors/Index.razor b/Oqtane.Client/Modules/Admin/Visitors/Index.razor index d09d8e0d..f0613839 100644 --- a/Oqtane.Client/Modules/Admin/Visitors/Index.razor +++ b/Oqtane.Client/Modules/Admin/Visitors/Index.razor @@ -2,6 +2,7 @@ @inherits ModuleBase @inject IVisitorService VisitorService @inject ISiteService SiteService +@inject ISettingService SettingService @inject IStringLocalizer Localizer @inject IStringLocalizer SharedLocalizer @@ -56,18 +57,30 @@ else @context.CreatedOn - +
- +
-
+
+ +
+ +
+
+
+ +
+ +
+

@@ -79,14 +92,18 @@ else private bool _users = false; private int _days = 1; private List _visitors; - private string _visitortracking; + private string _tracking; + private string _filter = ""; + private string _retention = ""; public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin; protected override async Task OnParametersSetAsync() { await GetVisitors(); - _visitortracking = PageState.Site.VisitorTracking.ToString(); + _tracking = PageState.Site.VisitorTracking.ToString(); + _filter = SettingService.GetSetting(PageState.Site.Settings, "VisitorFilter", ""); + _retention = SettingService.GetSetting(PageState.Site.Settings, "VisitorRetention", "30"); } private async void TypeChanged(ChangeEventArgs e) @@ -124,15 +141,21 @@ else { _visitors = _visitors.Where(item => item.UserId != null).ToList(); } - } + } private async Task SaveSiteSettings() { try { var site = PageState.Site; - site.VisitorTracking = bool.Parse(_visitortracking); + site.VisitorTracking = bool.Parse(_tracking); await SiteService.UpdateSiteAsync(site); + + var settings = PageState.Site.Settings; + settings = SettingService.SetSetting(settings, "VisitorFilter", _filter); + settings = SettingService.SetSetting(settings, "VisitorRetention", _retention); + await SettingService.UpdateSiteSettingsAsync(settings, PageState.Site.SiteId); + AddModuleMessage(Localizer["Success.SaveSiteSettings"], MessageType.Success); } catch (Exception ex) diff --git a/Oqtane.Client/Resources/Modules/Admin/Logs/Index.resx b/Oqtane.Client/Resources/Modules/Admin/Logs/Index.resx index 84d9994a..dfd55880 100644 --- a/Oqtane.Client/Resources/Modules/Admin/Logs/Index.resx +++ b/Oqtane.Client/Resources/Modules/Admin/Logs/Index.resx @@ -192,4 +192,22 @@ Details + + Error Saving Settings + + + Events + + + Number of days of events to retain + + + Retention (Days): + + + Settings + + + Settings Saved Successfully + \ No newline at end of file diff --git a/Oqtane.Client/Resources/Modules/Admin/Visitors/Index.resx b/Oqtane.Client/Resources/Modules/Admin/Visitors/Index.resx index c418f58e..a6e25bbc 100644 --- a/Oqtane.Client/Resources/Modules/Admin/Visitors/Index.resx +++ b/Oqtane.Client/Resources/Modules/Admin/Visitors/Index.resx @@ -156,11 +156,11 @@ Visitors - + Specify if visitor tracking is enabled - - Visitor Tracking Enabled? + + Tracking Enabled? IP @@ -174,4 +174,16 @@ Details + + Comma delimited list of terms which may exist in IP addresses, user agents, or languages which identify visitors which should not be tracked (ie. bots) + + + Filter: + + + Number of days of visitor activity to retain + + + Retention (Days): + \ No newline at end of file diff --git a/Oqtane.Client/Themes/Controls/Theme/ControlPanel.razor b/Oqtane.Client/Themes/Controls/Theme/ControlPanel.razor index 758a1bef..f5023748 100644 --- a/Oqtane.Client/Themes/Controls/Theme/ControlPanel.razor +++ b/Oqtane.Client/Themes/Controls/Theme/ControlPanel.razor @@ -218,188 +218,189 @@ @code{ - private bool _deleteConfirmation = false; - private List _categories = new List(); - private List _allModuleDefinitions; - private List _moduleDefinitions; - private List _pages = new List(); - private List _modules = new List(); - private List _containers = new List(); - private string _category = "Common"; + private bool _deleteConfirmation = false; + private List _categories = new List(); + private List _allModuleDefinitions; + private List _moduleDefinitions; + private List _pages = new List(); + private List _modules = new List(); + private List _containers = new List(); + private string _category = "Common"; - protected string PageId { get; private set; } = "-"; - protected string ModuleId { get; private set; } = "-"; - protected string ModuleType { get; private set; } = "new"; - protected string ModuleDefinitionName { get; private set; } = "-"; + protected string PageId { get; private set; } = "-"; + protected string ModuleId { get; private set; } = "-"; + protected string ModuleType { get; private set; } = "new"; + protected string ModuleDefinitionName { get; private set; } = "-"; - protected string Category - { - get => _category; - private set - { - if (_category != value) - { - _category = value; - _moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Contains(Category)).ToList(); - ModuleDefinitionName = "-"; - Description = ""; - StateHasChanged(); - _ = UpdateSettingsAsync(); - } - } - } + protected string Category + { + get => _category; + private set + { + if (_category != value) + { + _category = value; + _moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Contains(Category)).ToList(); + ModuleDefinitionName = "-"; + Description = ""; + StateHasChanged(); + _ = UpdateSettingsAsync(); + } + } + } - protected string Pane - { - get => _pane; - private set - { - if (_pane != value) - { - _pane = value; - _ = UpdateSettingsAsync(); - } - } - } + protected string Pane + { + get => _pane; + private set + { + if (_pane != value) + { + _pane = value; + _ = UpdateSettingsAsync(); + } + } + } - protected string Description { get; private set; } = ""; + protected string Description { get; private set; } = ""; - protected string Title { get; private set; } = ""; - protected string ContainerType { get; private set; } = ""; - protected string Message { get; private set; } = ""; + protected string Title { get; private set; } = ""; + protected string ContainerType { get; private set; } = ""; + protected string Message { get; private set; } = ""; - [Parameter] - public string ButtonClass { get; set; } = "btn-outline-secondary"; + [Parameter] + public string ButtonClass { get; set; } = "btn-outline-secondary"; - [Parameter] - public string ContainerClass { get; set; } = "offcanvas offcanvas-end"; + [Parameter] + public string ContainerClass { get; set; } = "offcanvas offcanvas-end"; - [Parameter] - public string HeaderClass { get; set; } = "offcanvas-header"; + [Parameter] + public string HeaderClass { get; set; } = "offcanvas-header"; - [Parameter] - public string BodyClass { get; set; } = "offcanvas-body overflow-auto"; + [Parameter] + public string BodyClass { get; set; } = "offcanvas-body overflow-auto"; - [Parameter] - public bool ShowLanguageSwitcher { get; set; } = true; + [Parameter] + public bool ShowLanguageSwitcher { get; set; } = true; - protected override async Task OnParametersSetAsync() - { - if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions)) - { - _pages?.Clear(); + protected override async Task OnParametersSetAsync() + { + if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions)) + { + _pages?.Clear(); - foreach (Page p in PageState.Pages) - { - if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.Permissions)) - { - _pages.Add(p); - } - } - await LoadSettingsAsync(); + foreach (Page p in PageState.Pages) + { + if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.Permissions)) + { + _pages.Add(p); + } + } + await LoadSettingsAsync(); - var themes = await ThemeService.GetThemesAsync(); - _containers = ThemeService.GetContainerControls(themes, PageState.Page.ThemeType); - ContainerType = PageState.Site.DefaultContainerType; - _allModuleDefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId); - _moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Contains(Category)).ToList(); - _categories = _allModuleDefinitions.SelectMany(m => m.Categories.Split(',')).Distinct().ToList(); - } - } + var themes = await ThemeService.GetThemesAsync(); + _containers = ThemeService.GetContainerControls(themes, PageState.Page.ThemeType); + ContainerType = PageState.Site.DefaultContainerType; + _allModuleDefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId); + _moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Contains(Category)).ToList(); + _categories = _allModuleDefinitions.SelectMany(m => m.Categories.Split(',')).Distinct().ToList(); + } + } - private void CategoryChanged(ChangeEventArgs e) - { - Category = (string)e.Value; - } + private void CategoryChanged(ChangeEventArgs e) + { + Category = (string)e.Value; + } - private void ModuleChanged(ChangeEventArgs e) - { - ModuleDefinitionName = (string)e.Value; - if (ModuleDefinitionName != "-") - { - var moduleDefinition = _moduleDefinitions.FirstOrDefault(item => item.ModuleDefinitionName == ModuleDefinitionName); - Description = "
" + moduleDefinition.Description + "
"; - } - else - { - Description = ""; - } + private void ModuleChanged(ChangeEventArgs e) + { + ModuleDefinitionName = (string)e.Value; + if (ModuleDefinitionName != "-") + { + var moduleDefinition = _moduleDefinitions.FirstOrDefault(item => item.ModuleDefinitionName == ModuleDefinitionName); + Description = "
" + moduleDefinition.Description + "
"; + } + else + { + Description = ""; + } - StateHasChanged(); - } + StateHasChanged(); + } - private void PageChanged(ChangeEventArgs e) - { - PageId = (string)e.Value; - if (PageId != "-") - { - _modules = PageState.Modules - .Where(module => module.PageId == int.Parse(PageId) - && !module.IsDeleted - && UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, module.Permissions)) - .ToList(); - } - ModuleId = "-"; - StateHasChanged(); - } + private void PageChanged(ChangeEventArgs e) + { + PageId = (string)e.Value; + if (PageId != "-") + { + _modules = PageState.Modules + .Where(module => module.PageId == int.Parse(PageId) + && !module.IsDeleted + && UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, module.Permissions)) + .ToList(); + } + ModuleId = "-"; + StateHasChanged(); + } - private async Task AddModule() - { - if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions)) - { - if ((ModuleType == "new" && ModuleDefinitionName != "-") || (ModuleType != "new" && ModuleId != "-")) - { - if (ModuleType == "new") - { - Module module = new Module(); - module.SiteId = PageState.Site.SiteId; - module.PageId = PageState.Page.PageId; - module.ModuleDefinitionName = ModuleDefinitionName; - module.AllPages = false; + private async Task AddModule() + { + if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions)) + { + if ((ModuleType == "new" && ModuleDefinitionName != "-") || (ModuleType != "new" && ModuleId != "-")) + { + if (ModuleType == "new") + { + Module module = new Module(); + module.SiteId = PageState.Site.SiteId; + module.PageId = PageState.Page.PageId; + module.ModuleDefinitionName = ModuleDefinitionName; + module.AllPages = false; - // set module view permissions to page edit permissions - List permissions = UserSecurity.GetPermissionStrings(PageState.Page.Permissions); - permissions.Find(p => p.PermissionName == PermissionNames.View).Permissions = permissions.Find(p => p.PermissionName == PermissionNames.Edit).Permissions; - module.Permissions = UserSecurity.SetPermissionStrings(permissions); + // set module view permissions to page edit permissions + List permissions = UserSecurity.GetPermissionStrings(PageState.Page.Permissions); + permissions.Find(p => p.PermissionName == PermissionNames.View).Permissions = permissions.Find(p => p.PermissionName == PermissionNames.Edit).Permissions; + module.Permissions = UserSecurity.SetPermissionStrings(permissions); - module = await ModuleService.AddModuleAsync(module); - ModuleId = module.ModuleId.ToString(); - } + module = await ModuleService.AddModuleAsync(module); + ModuleId = module.ModuleId.ToString(); + } - var pageModule = new PageModule + var pageModule = new PageModule { PageId = PageState.Page.PageId, ModuleId = int.Parse(ModuleId), Title = Title }; - if (pageModule.Title == "") - { - if (ModuleType == "new") - { - pageModule.Title = _moduleDefinitions.FirstOrDefault(item => item.ModuleDefinitionName == ModuleDefinitionName)?.Name; - } - else - { - pageModule.Title = _modules.FirstOrDefault(item => item.ModuleId == int.Parse(ModuleId))?.Title; - } - } + if (pageModule.Title == "") + { + if (ModuleType == "new") + { + pageModule.Title = _moduleDefinitions.FirstOrDefault(item => item.ModuleDefinitionName == ModuleDefinitionName)?.Name; + } + else + { + pageModule.Title = _modules.FirstOrDefault(item => item.ModuleId == int.Parse(ModuleId))?.Title; + } + } - pageModule.Pane = Pane; - pageModule.Order = int.MaxValue; - pageModule.ContainerType = ContainerType; + pageModule.Pane = Pane; + pageModule.Order = int.MaxValue; + pageModule.ContainerType = ContainerType; - if (pageModule.ContainerType == PageState.Site.DefaultContainerType) - { - pageModule.ContainerType = ""; - } + if (pageModule.ContainerType == PageState.Site.DefaultContainerType) + { + pageModule.ContainerType = ""; + } - await PageModuleService.AddPageModuleAsync(pageModule); - await PageModuleService.UpdatePageModuleOrderAsync(pageModule.PageId, pageModule.Pane); + await PageModuleService.AddPageModuleAsync(pageModule); + await PageModuleService.UpdatePageModuleOrderAsync(pageModule.PageId, pageModule.Pane); - Message = $"
{Localizer["Success.Page.ModuleAdd"]}
"; - NavigationManager.NavigateTo(NavigateUrl()); + Message = $"
{Localizer["Success.Page.ModuleAdd"]}
"; + Title = ""; + NavigationManager.NavigateTo(NavigateUrl()); } else { diff --git a/Oqtane.Server/Infrastructure/Jobs/PurgeJob.cs b/Oqtane.Server/Infrastructure/Jobs/PurgeJob.cs new file mode 100644 index 00000000..695f12c8 --- /dev/null +++ b/Oqtane.Server/Infrastructure/Jobs/PurgeJob.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Extensions.DependencyInjection; +using Oqtane.Models; +using Oqtane.Repository; +using Oqtane.Shared; + +namespace Oqtane.Infrastructure +{ + public class PurgeJob : HostedServiceBase + { + // JobType = "Oqtane.Infrastructure.PurgeJob, Oqtane.Server" + + public PurgeJob(IServiceScopeFactory serviceScopeFactory) : base(serviceScopeFactory) + { + Name = "Purge Job"; + Frequency = "d"; // daily + Interval = 1; + StartDate = DateTime.ParseExact("03:00", "H:mm", null, System.Globalization.DateTimeStyles.None); // 3 AM + IsEnabled = true; + } + + // job is executed for each tenant in installation + public override string ExecuteJob(IServiceProvider provider) + { + string log = ""; + + // get services + var siteRepository = provider.GetRequiredService(); + var settingRepository = provider.GetRequiredService(); + var logRepository = provider.GetRequiredService(); + var visitorRepository = provider.GetRequiredService(); + + // iterate through sites for current tenant + List sites = siteRepository.GetSites().ToList(); + foreach (Site site in sites) + { + log += "Processing Site: " + site.Name + "
"; + + // get site settings + Dictionary settings = GetSettings(settingRepository.GetSettings(EntityNames.Site, site.SiteId).ToList()); + + // purge event log + int logretention = 30; + if (settings.ContainsKey("LogRetention") && settings["LogRetention"] != "") + { + logretention = int.Parse(settings["LogRetention"]); + } + int count = logRepository.DeleteLogs(logretention); + log += count.ToString() + " Event Logs Purged
"; + + // purge visitors + int visitorrention = 30; + if (settings.ContainsKey("VisitorRetention") && settings["VisitorRetention"] != "") + { + visitorrention = int.Parse(settings["VisitorRetention"]); + } + count = visitorRepository.DeleteVisitors(visitorrention); + log += count.ToString() + " Visitors Purged
"; + } + + return log; + } + + private Dictionary GetSettings(List settings) + { + Dictionary dictionary = new Dictionary(); + foreach (Setting setting in settings.OrderBy(item => item.SettingName).ToList()) + { + dictionary.Add(setting.SettingName, setting.SettingValue); + } + return dictionary; + } + } +} diff --git a/Oqtane.Server/Pages/_Host.cshtml.cs b/Oqtane.Server/Pages/_Host.cshtml.cs index 3bb360a2..66c4b0cc 100644 --- a/Oqtane.Server/Pages/_Host.cshtml.cs +++ b/Oqtane.Server/Pages/_Host.cshtml.cs @@ -35,8 +35,9 @@ namespace Oqtane.Pages private readonly IUrlMappingRepository _urlMappings; private readonly IVisitorRepository _visitors; private readonly IAliasRepository _aliases; + private readonly ISettingRepository _settings; - public HostModel(IConfiguration configuration, ITenantManager tenantManager, ILocalizationManager localizationManager, ILanguageRepository languages, IAntiforgery antiforgery, ISiteRepository sites, IPageRepository pages, IUrlMappingRepository urlMappings, IVisitorRepository visitors, IAliasRepository aliases) + public HostModel(IConfiguration configuration, ITenantManager tenantManager, ILocalizationManager localizationManager, ILanguageRepository languages, IAntiforgery antiforgery, ISiteRepository sites, IPageRepository pages, IUrlMappingRepository urlMappings, IVisitorRepository visitors, IAliasRepository aliases, ISettingRepository settings) { _configuration = configuration; _tenantManager = tenantManager; @@ -48,6 +49,7 @@ namespace Oqtane.Pages _urlMappings = urlMappings; _visitors = visitors; _aliases = aliases; + _settings = settings; } public string AntiForgeryToken = ""; @@ -198,6 +200,20 @@ namespace Oqtane.Pages language = (language.Contains(",")) ? language.Substring(0, language.IndexOf(",")) : language; language = (language.Contains(";")) ? language.Substring(0, language.IndexOf(";")) : language; language = (language.Trim().Length == 0) ? "*" : language; + + // filter + var filter = _settings.GetSetting(EntityNames.Site, SiteId, "VisitorFilter"); + if (filter != null && !string.IsNullOrEmpty(filter.SettingValue)) + { + foreach (string term in filter.SettingValue.ToLower().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(sValue => sValue.Trim()).ToArray()) + { + if (ip.ToLower().Contains(term) || useragent.ToLower().Contains(term) || language.ToLower().Contains(term)) + { + return; + } + } + } + string url = Request.GetEncodedUrl(); string referrer = (Request.Headers[HeaderNames.Referer] != StringValues.Empty) ? Request.Headers[HeaderNames.Referer] : ""; int? userid = null; diff --git a/Oqtane.Server/Repository/Interfaces/ILogRepository.cs b/Oqtane.Server/Repository/Interfaces/ILogRepository.cs index 27752a03..cc2c8aae 100644 --- a/Oqtane.Server/Repository/Interfaces/ILogRepository.cs +++ b/Oqtane.Server/Repository/Interfaces/ILogRepository.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using Oqtane.Models; namespace Oqtane.Repository @@ -8,5 +8,6 @@ namespace Oqtane.Repository IEnumerable GetLogs(int siteId, string level, string function, int rows); Log GetLog(int logId); void AddLog(Log log); + int DeleteLogs(int age); } } diff --git a/Oqtane.Server/Repository/Interfaces/ISettingRepository.cs b/Oqtane.Server/Repository/Interfaces/ISettingRepository.cs index 0f6728f1..5c231806 100644 --- a/Oqtane.Server/Repository/Interfaces/ISettingRepository.cs +++ b/Oqtane.Server/Repository/Interfaces/ISettingRepository.cs @@ -10,6 +10,7 @@ namespace Oqtane.Repository Setting AddSetting(Setting setting); Setting UpdateSetting(Setting setting); Setting GetSetting(string entityName, int settingId); + Setting GetSetting(string entityName, int entityId, string settingName); void DeleteSetting(string entityName, int settingId); void DeleteSettings(string entityName, int entityId); } diff --git a/Oqtane.Server/Repository/Interfaces/IVisitorRepository.cs b/Oqtane.Server/Repository/Interfaces/IVisitorRepository.cs index d50ceec2..3b05ba90 100644 --- a/Oqtane.Server/Repository/Interfaces/IVisitorRepository.cs +++ b/Oqtane.Server/Repository/Interfaces/IVisitorRepository.cs @@ -11,5 +11,6 @@ namespace Oqtane.Repository Visitor UpdateVisitor(Visitor visitor); Visitor GetVisitor(int visitorId); void DeleteVisitor(int visitorId); + int DeleteVisitors(int age); } } diff --git a/Oqtane.Server/Repository/LogRepository.cs b/Oqtane.Server/Repository/LogRepository.cs index 1bcbc2be..1d67aaab 100644 --- a/Oqtane.Server/Repository/LogRepository.cs +++ b/Oqtane.Server/Repository/LogRepository.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using Oqtane.Models; @@ -47,5 +48,23 @@ namespace Oqtane.Repository _db.Log.Add(log); _db.SaveChanges(); } + + public int DeleteLogs(int age) + { + // delete logs in batches of 100 records + int count = 0; + var purgedate = DateTime.Now.AddDays(-age); + var logs = _db.Log.Where(item => item.Level != "Error" && item.LogDate < purgedate) + .OrderBy(item => item.LogDate).Take(100).ToList(); + while (logs.Count > 0) + { + count += logs.Count; + _db.Log.RemoveRange(logs); + _db.SaveChanges(); + logs = _db.Log.Where(item => item.Level != "Error" && item.LogDate < purgedate) + .OrderBy(item => item.LogDate).Take(100).ToList(); + } + return count; + } } } diff --git a/Oqtane.Server/Repository/SettingRepository.cs b/Oqtane.Server/Repository/SettingRepository.cs index c87a1df3..95b55de6 100644 --- a/Oqtane.Server/Repository/SettingRepository.cs +++ b/Oqtane.Server/Repository/SettingRepository.cs @@ -77,6 +77,18 @@ namespace Oqtane.Repository } } + public Setting GetSetting(string entityName, int entityId, string settingName) + { + if (IsMaster(entityName)) + { + return _master.Setting.Where(item => item.EntityName == entityName && item.EntityId == entityId && item.SettingName == settingName).FirstOrDefault(); + } + else + { + return _tenant.Setting.Where(item => item.EntityName == entityName && item.EntityId == entityId && item.SettingName == settingName).FirstOrDefault(); + } + } + public void DeleteSetting(string entityName, int settingId) { if (IsMaster(entityName)) diff --git a/Oqtane.Server/Repository/VisitorRepository.cs b/Oqtane.Server/Repository/VisitorRepository.cs index 254c48e7..5feeaad9 100644 --- a/Oqtane.Server/Repository/VisitorRepository.cs +++ b/Oqtane.Server/Repository/VisitorRepository.cs @@ -47,5 +47,23 @@ namespace Oqtane.Repository _db.Visitor.Remove(visitor); _db.SaveChanges(); } + + public int DeleteVisitors(int age) + { + // delete visitors in batches of 100 records + int count = 0; + var purgedate = DateTime.Now.AddDays(-age); + var visitors = _db.Visitor.Where(item => item.Visits <= 1 && item.VisitedOn < purgedate) + .OrderBy(item => item.VisitedOn).Take(100).ToList(); + while (visitors.Count > 0) + { + count += visitors.Count; + _db.Visitor.RemoveRange(visitors); + _db.SaveChanges(); + visitors = _db.Visitor.Where(item => item.Visits < 2 && item.VisitedOn < purgedate) + .OrderBy(item => item.VisitedOn).Take(100).ToList(); + } + return count; + } } }