Merge pull request #1861 from sbwalker/dev
added support for url mapping and viitors
This commit is contained in:
		| @ -164,6 +164,14 @@ namespace Oqtane.Controllers | ||||
|                         authorized = User.IsInRole(RoleNames.Admin) || (_userPermissions.GetUser(User).UserId == entityId); | ||||
|                     } | ||||
|                     break; | ||||
|                 case EntityNames.Visitor: | ||||
|                     authorized = false; | ||||
|                     var visitorCookie = "APP_VISITOR_" + _alias.SiteId.ToString(); | ||||
|                     if (int.TryParse(Request.Cookies[visitorCookie], out int visitorId)) | ||||
|                     { | ||||
|                         authorized = (visitorId == entityId); | ||||
|                     } | ||||
|                     break; | ||||
|             } | ||||
|             return authorized; | ||||
|         } | ||||
|  | ||||
							
								
								
									
										119
									
								
								Oqtane.Server/Controllers/UrlMappingController.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								Oqtane.Server/Controllers/UrlMappingController.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,119 @@ | ||||
| using System.Collections.Generic; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| using Oqtane.Enums; | ||||
| using Oqtane.Models; | ||||
| using Oqtane.Shared; | ||||
| using Oqtane.Infrastructure; | ||||
| using Oqtane.Repository; | ||||
| using System.Net; | ||||
|  | ||||
| namespace Oqtane.Controllers | ||||
| { | ||||
|     [Route(ControllerRoutes.ApiRoute)] | ||||
|     public class UrlMappingController : Controller | ||||
|     { | ||||
|         private readonly IUrlMappingRepository _urlMappings; | ||||
|         private readonly ILogManager _logger; | ||||
|         private readonly Alias _alias; | ||||
|  | ||||
|         public UrlMappingController(IUrlMappingRepository urlMappings, ILogManager logger, ITenantManager tenantManager) | ||||
|         { | ||||
|             _urlMappings = urlMappings; | ||||
|             _logger = logger; | ||||
|             _alias = tenantManager.GetAlias(); | ||||
|         } | ||||
|  | ||||
|         // GET: api/<controller>?siteid=x&ismapped=y | ||||
|         [HttpGet] | ||||
|         [Authorize(Roles = RoleNames.Admin)] | ||||
|         public IEnumerable<UrlMapping> Get(string siteid, string ismapped) | ||||
|         { | ||||
|             int SiteId; | ||||
|             if (int.TryParse(siteid, out SiteId) && SiteId == _alias.SiteId) | ||||
|             { | ||||
|                 return _urlMappings.GetUrlMappings(SiteId, bool.Parse(ismapped)); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized UrlMapping Get Attempt {SiteId}", siteid); | ||||
|                 HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden; | ||||
|                 return null; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // GET api/<controller>/5 | ||||
|         [HttpGet("{id}")] | ||||
|         [Authorize(Roles = RoleNames.Admin)] | ||||
|         public UrlMapping Get(int id) | ||||
|         { | ||||
|             var urlMapping = _urlMappings.GetUrlMapping(id); | ||||
|             if (urlMapping != null && (urlMapping.SiteId == _alias.SiteId)) | ||||
|             { | ||||
|                 return urlMapping; | ||||
|             } | ||||
|             else | ||||
|             {  | ||||
|                 _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized UrlMapping Get Attempt {UrlMappingId}", id); | ||||
|                 HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden; | ||||
|                 return null; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // POST api/<controller> | ||||
|         [HttpPost] | ||||
|         [Authorize(Roles = RoleNames.Admin)] | ||||
|         public UrlMapping Post([FromBody] UrlMapping urlMapping) | ||||
|         { | ||||
|             if (ModelState.IsValid && urlMapping.SiteId == _alias.SiteId) | ||||
|             { | ||||
|                 urlMapping = _urlMappings.AddUrlMapping(urlMapping); | ||||
|                 _logger.Log(LogLevel.Information, this, LogFunction.Create, "UrlMapping Added {UrlMapping}", urlMapping); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized UrlMapping Post Attempt {Role}", urlMapping); | ||||
|                 HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden; | ||||
|                 urlMapping = null; | ||||
|             } | ||||
|             return urlMapping; | ||||
|         } | ||||
|  | ||||
|         // PUT api/<controller>/5 | ||||
|         [HttpPut("{id}")] | ||||
|         [Authorize(Roles = RoleNames.Admin)] | ||||
|         public UrlMapping Put(int id, [FromBody] UrlMapping urlMapping) | ||||
|         { | ||||
|             if (ModelState.IsValid && urlMapping.SiteId == _alias.SiteId && _urlMappings.GetUrlMapping(urlMapping.UrlMappingId, false) != null) | ||||
|             { | ||||
|                 urlMapping = _urlMappings.UpdateUrlMapping(urlMapping); | ||||
|                 _logger.Log(LogLevel.Information, this, LogFunction.Update, "UrlMapping Updated {UrlMapping}", urlMapping); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized UrlMapping Put Attempt {UrlMapping}", urlMapping); | ||||
|                 HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden; | ||||
|                 urlMapping = null; | ||||
|             } | ||||
|             return urlMapping; | ||||
|         } | ||||
|  | ||||
|         // DELETE api/<controller>/5 | ||||
|         [HttpDelete("{id}")] | ||||
|         [Authorize(Roles = RoleNames.Admin)] | ||||
|         public void Delete(int id) | ||||
|         { | ||||
|             var urlMapping = _urlMappings.GetUrlMapping(id); | ||||
|             if (urlMapping != null && urlMapping.SiteId == _alias.SiteId) | ||||
|             { | ||||
|                 _urlMappings.DeleteUrlMapping(id); | ||||
|                 _logger.Log(LogLevel.Information, this, LogFunction.Delete, "UrlMapping Deleted {UrlMappingId}", id); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized UrlMapping Delete Attempt {UrlMappingId}", id); | ||||
|                 HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										46
									
								
								Oqtane.Server/Controllers/VisitorController.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								Oqtane.Server/Controllers/VisitorController.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,46 @@ | ||||
| using System.Collections.Generic; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| using Oqtane.Enums; | ||||
| using Oqtane.Models; | ||||
| using Oqtane.Shared; | ||||
| using Oqtane.Infrastructure; | ||||
| using Oqtane.Repository; | ||||
| using System.Net; | ||||
| using System; | ||||
|  | ||||
| namespace Oqtane.Controllers | ||||
| { | ||||
|     [Route(ControllerRoutes.ApiRoute)] | ||||
|     public class VisitorController : Controller | ||||
|     { | ||||
|         private readonly IVisitorRepository _visitors; | ||||
|         private readonly ILogManager _logger; | ||||
|         private readonly Alias _alias; | ||||
|  | ||||
|         public VisitorController(IVisitorRepository visitors, ILogManager logger, ITenantManager tenantManager) | ||||
|         { | ||||
|             _visitors = visitors; | ||||
|             _logger = logger; | ||||
|             _alias = tenantManager.GetAlias(); | ||||
|         } | ||||
|  | ||||
|         // GET: api/<controller>?siteid=x&fromdate=y | ||||
|         [HttpGet] | ||||
|         [Authorize(Roles = RoleNames.Admin)] | ||||
|         public IEnumerable<Visitor> Get(string siteid, string fromdate) | ||||
|         { | ||||
|             int SiteId; | ||||
|             if (int.TryParse(siteid, out SiteId) && SiteId == _alias.SiteId) | ||||
|             { | ||||
|                 return _visitors.GetVisitors(SiteId, DateTime.Parse(fromdate)); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Visitor Get Attempt {SiteId}", siteid); | ||||
|                 HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden; | ||||
|                 return null; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -98,6 +98,8 @@ namespace Microsoft.Extensions.DependencyInjection | ||||
|             services.AddTransient<ISqlRepository, SqlRepository>(); | ||||
|             services.AddTransient<IUpgradeManager, UpgradeManager>(); | ||||
|             services.AddTransient<ILanguageRepository, LanguageRepository>(); | ||||
|             services.AddTransient<IVisitorRepository, VisitorRepository>(); | ||||
|             services.AddTransient<IUrlMappingRepository, UrlMappingRepository>(); | ||||
|             // obsolete - replaced by ITenantManager | ||||
|             services.AddTransient<ITenantResolver, TenantResolver>(); | ||||
|  | ||||
|  | ||||
| @ -582,12 +582,19 @@ namespace Oqtane.Infrastructure | ||||
|                                 TenantId = tenant.TenantId, | ||||
|                                 Name = install.SiteName, | ||||
|                                 LogoFileId = null, | ||||
|                                 FaviconFileId = null, | ||||
|                                 PwaIsEnabled = false, | ||||
|                                 PwaAppIconFileId = null, | ||||
|                                 PwaSplashIconFileId = null, | ||||
|                                 AllowRegistration = false, | ||||
|                                 CaptureBrokenUrls = true, | ||||
|                                 VisitorTracking = true, | ||||
|                                 DefaultThemeType = (!string.IsNullOrEmpty(install.DefaultTheme)) ? install.DefaultTheme : Constants.DefaultTheme, | ||||
|                                 DefaultContainerType = (!string.IsNullOrEmpty(install.DefaultContainer)) ? install.DefaultContainer : Constants.DefaultContainer, | ||||
|                                 AdminContainerType = (!string.IsNullOrEmpty(install.DefaultAdminContainer)) ? install.DefaultAdminContainer : Constants.DefaultAdminContainer, | ||||
|                                 SiteTemplateType = install.SiteTemplate, | ||||
|                                 Runtime = (!string.IsNullOrEmpty(install.Runtime)) ? install.Runtime : _configManager.GetSection("Runtime").Value, | ||||
|                                 RenderMode = (!string.IsNullOrEmpty(install.RenderMode)) ? install.RenderMode : _configManager.GetSection("RenderMode").Value | ||||
|                                 RenderMode = (!string.IsNullOrEmpty(install.RenderMode)) ? install.RenderMode : _configManager.GetSection("RenderMode").Value, | ||||
|                             }; | ||||
|                             site = sites.AddSite(site); | ||||
|  | ||||
|  | ||||
| @ -2,6 +2,7 @@ using Microsoft.AspNetCore.Hosting; | ||||
| using Microsoft.Extensions.Configuration; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Newtonsoft.Json; | ||||
| using Oqtane.Extensions; | ||||
| using Oqtane.Models; | ||||
| using Oqtane.Repository; | ||||
| using Oqtane.Shared; | ||||
| @ -37,9 +38,6 @@ namespace Oqtane.Infrastructure | ||||
|  | ||||
|                 switch (version) | ||||
|                 { | ||||
|                     case "1.0.0": | ||||
|                         Upgrade_1_0_0(tenant, scope); | ||||
|                         break; | ||||
|                     case "2.0.2": | ||||
|                         Upgrade_2_0_2(tenant, scope); | ||||
|                         break; | ||||
| @ -49,61 +47,13 @@ namespace Oqtane.Infrastructure | ||||
|                     case "2.2.0": | ||||
|                         Upgrade_2_2_0(tenant, scope); | ||||
|                         break; | ||||
|                     case "3.0.1": | ||||
|                         Upgrade_3_0_1(tenant, scope); | ||||
|                         break; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// **Note: this code is commented out on purpose - it provides an example of how to programmatically add a page to all existing sites on upgrade | ||||
|         /// </summary> | ||||
|         /// <param name="tenant"></param> | ||||
|         /// <param name="scope"></param> | ||||
|         private void Upgrade_1_0_0(Tenant tenant, IServiceScope scope) | ||||
|         { | ||||
|             //var pageTemplates = new List<PageTemplate>(); | ||||
|             // | ||||
|             //pageTemplates.Add(new PageTemplate | ||||
|             //{ | ||||
|             //    Name = "Test", | ||||
|             //    Parent = "", | ||||
|             //    Order = 1, | ||||
|             //    Path = "test", | ||||
|             //    Icon = Icons.Badge, | ||||
|             //    IsNavigation = true, | ||||
|             //    IsPersonalizable = false, | ||||
|             //    IsClickable = true, | ||||
|             //    PagePermissions = new List<Permission> | ||||
|             //    { | ||||
|             //        new Permission(PermissionNames.View, RoleNames.Admin, true), | ||||
|             //        new Permission(PermissionNames.View, RoleNames.Everyone, true), | ||||
|             //        new Permission(PermissionNames.Edit, RoleNames.Admin, true) | ||||
|             //    }.EncodePermissions(), | ||||
|             //            PageTemplateModules = new List<PageTemplateModule> | ||||
|             //    { | ||||
|             //        new PageTemplateModule | ||||
|             //        { | ||||
|             //            ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Login.Index).ToModuleDefinitionName(), Title = "Test", Pane = "Content", | ||||
|             //            ModulePermissions = new List<Permission> | ||||
|             //            { | ||||
|             //                new Permission(PermissionNames.View, RoleNames.Admin, true), | ||||
|             //                new Permission(PermissionNames.View, RoleNames.Everyone, true), | ||||
|             //                new Permission(PermissionNames.Edit, RoleNames.Admin, true) | ||||
|             //            }.EncodePermissions(), | ||||
|             //            Content = "" | ||||
|             //        } | ||||
|             //    } | ||||
|             //}); | ||||
|             // | ||||
|             //if (pageTemplates.Count != 0) | ||||
|             //{ | ||||
|             //    var sites = scope.ServiceProvider.GetRequiredService<ISiteRepository>(); | ||||
|             //    foreach (Site site in sites.GetSites().ToList()) | ||||
|             //    { | ||||
|             //        sites.CreatePages(site, pageTemplates); | ||||
|             //    } | ||||
|             //} | ||||
|         } | ||||
|  | ||||
|         private void Upgrade_2_0_2(Tenant tenant, IServiceScope scope) | ||||
|         { | ||||
|             if (tenant.Name == TenantNames.Master) | ||||
| @ -163,5 +113,74 @@ namespace Oqtane.Infrastructure | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private void Upgrade_3_0_1(Tenant tenant, IServiceScope scope) | ||||
|         { | ||||
|             var pageTemplates = new List<PageTemplate>(); | ||||
|  | ||||
|             pageTemplates.Add(new PageTemplate | ||||
|             { | ||||
|                 Name = "Url Mappings", | ||||
|                 Parent = "Admin", | ||||
|                 Order = 33, | ||||
|                 Path = "admin/urlmappings", | ||||
|                 Icon = Icons.LinkBroken, | ||||
|                 IsNavigation = true, | ||||
|                 IsPersonalizable = false, | ||||
|                 PagePermissions = new List<Permission> | ||||
|                 { | ||||
|                     new Permission(PermissionNames.View, RoleNames.Admin, true), | ||||
|                     new Permission(PermissionNames.Edit, RoleNames.Admin, true) | ||||
|                 }.EncodePermissions(), | ||||
|                 PageTemplateModules = new List<PageTemplateModule> | ||||
|                 { | ||||
|                     new PageTemplateModule | ||||
|                     { | ||||
|                         ModuleDefinitionName = typeof(Oqtane.Modules.Admin.UrlMappings.Index).ToModuleDefinitionName(), Title = "Url Mappings", Pane = PaneNames.Admin, | ||||
|                         ModulePermissions = new List<Permission> | ||||
|                         { | ||||
|                             new Permission(PermissionNames.View, RoleNames.Admin, true), | ||||
|                             new Permission(PermissionNames.Edit, RoleNames.Admin, true) | ||||
|                         }.EncodePermissions(), | ||||
|                         Content = "" | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             pageTemplates.Add(new PageTemplate | ||||
|             { | ||||
|                 Name = "Visitor Management", | ||||
|                 Parent = "Admin", | ||||
|                 Order = 35, | ||||
|                 Path = "admin/visitors", | ||||
|                 Icon = Icons.Eye, | ||||
|                 IsNavigation = true, | ||||
|                 IsPersonalizable = false, | ||||
|                 PagePermissions = new List<Permission> | ||||
|                 { | ||||
|                     new Permission(PermissionNames.View, RoleNames.Admin, true), | ||||
|                     new Permission(PermissionNames.Edit, RoleNames.Admin, true) | ||||
|                 }.EncodePermissions(), | ||||
|                 PageTemplateModules = new List<PageTemplateModule> | ||||
|                 { | ||||
|                     new PageTemplateModule | ||||
|                     { | ||||
|                         ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Visitors.Index).ToModuleDefinitionName(), Title = "Visitor Management", Pane = PaneNames.Admin, | ||||
|                         ModulePermissions = new List<Permission> | ||||
|                         { | ||||
|                             new Permission(PermissionNames.View, RoleNames.Admin, true), | ||||
|                             new Permission(PermissionNames.Edit, RoleNames.Admin, true) | ||||
|                         }.EncodePermissions(), | ||||
|                         Content = "" | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             var sites = scope.ServiceProvider.GetRequiredService<ISiteRepository>(); | ||||
|             foreach (Site site in sites.GetSites().ToList()) | ||||
|             { | ||||
|                 sites.CreatePages(site, pageTemplates); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -0,0 +1,51 @@ | ||||
| using Microsoft.EntityFrameworkCore.Migrations; | ||||
| using Microsoft.EntityFrameworkCore.Migrations.Operations; | ||||
| using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; | ||||
| using Oqtane.Databases.Interfaces; | ||||
|  | ||||
| // ReSharper disable MemberCanBePrivate.Global | ||||
| // ReSharper disable UnusedAutoPropertyAccessor.Global | ||||
|  | ||||
| namespace Oqtane.Migrations.EntityBuilders | ||||
| { | ||||
|     public class UrlMappingEntityBuilder : BaseEntityBuilder<UrlMappingEntityBuilder> | ||||
|     { | ||||
|         private const string _entityTableName = "UrlMapping"; | ||||
|         private readonly PrimaryKey<UrlMappingEntityBuilder> _primaryKey = new("PK_UrlMapping", x => x.UrlMappingId); | ||||
|         private readonly ForeignKey<UrlMappingEntityBuilder> _urlMappingForeignKey = new("FK_UrlMapping_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade); | ||||
|  | ||||
|         public UrlMappingEntityBuilder(MigrationBuilder migrationBuilder, IDatabase database) : base(migrationBuilder, database) | ||||
|         { | ||||
|             EntityTableName = _entityTableName; | ||||
|             PrimaryKey = _primaryKey; | ||||
|             ForeignKeys.Add(_urlMappingForeignKey); | ||||
|         } | ||||
|  | ||||
|         protected override UrlMappingEntityBuilder BuildTable(ColumnsBuilder table) | ||||
|         { | ||||
|             UrlMappingId = AddAutoIncrementColumn(table, "UrlMappingId"); | ||||
|             SiteId = AddIntegerColumn(table, "SiteId"); | ||||
|             Url = AddStringColumn(table, "Url", 500); | ||||
|             MappedUrl = AddStringColumn(table, "MappedUrl", 500); | ||||
|             Requests = AddIntegerColumn(table, "Requests"); | ||||
|             CreatedOn = AddDateTimeColumn(table, "CreatedOn"); | ||||
|             RequestedOn = AddDateTimeColumn(table, "RequestedOn"); | ||||
|  | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         public OperationBuilder<AddColumnOperation> UrlMappingId { get; private set; } | ||||
|  | ||||
|         public OperationBuilder<AddColumnOperation> SiteId { get; private set; } | ||||
|  | ||||
|         public OperationBuilder<AddColumnOperation> Url { get; private set; } | ||||
|  | ||||
|         public OperationBuilder<AddColumnOperation> MappedUrl { get; private set; } | ||||
|  | ||||
|         public OperationBuilder<AddColumnOperation> Requests { get; private set; } | ||||
|  | ||||
|         public OperationBuilder<AddColumnOperation> CreatedOn { get; private set; } | ||||
|  | ||||
|         public OperationBuilder<AddColumnOperation> RequestedOn { get; private set; } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,57 @@ | ||||
| using Microsoft.EntityFrameworkCore.Migrations; | ||||
| using Microsoft.EntityFrameworkCore.Migrations.Operations; | ||||
| using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; | ||||
| using Oqtane.Databases.Interfaces; | ||||
|  | ||||
| // ReSharper disable MemberCanBePrivate.Global | ||||
| // ReSharper disable UnusedAutoPropertyAccessor.Global | ||||
|  | ||||
| namespace Oqtane.Migrations.EntityBuilders | ||||
| { | ||||
|     public class VisitorEntityBuilder : BaseEntityBuilder<VisitorEntityBuilder> | ||||
|     { | ||||
|         private const string _entityTableName = "Visitor"; | ||||
|         private readonly PrimaryKey<VisitorEntityBuilder> _primaryKey = new("PK_Visitor", x => x.VisitorId); | ||||
|         private readonly ForeignKey<VisitorEntityBuilder> _visitorForeignKey = new("FK_Visitor_Site", x => x.SiteId, "Site", "SiteId", ReferentialAction.Cascade); | ||||
|  | ||||
|         public VisitorEntityBuilder(MigrationBuilder migrationBuilder, IDatabase database) : base(migrationBuilder, database) | ||||
|         { | ||||
|             EntityTableName = _entityTableName; | ||||
|             PrimaryKey = _primaryKey; | ||||
|             ForeignKeys.Add(_visitorForeignKey); | ||||
|         } | ||||
|  | ||||
|         protected override VisitorEntityBuilder BuildTable(ColumnsBuilder table) | ||||
|         { | ||||
|             VisitorId = AddAutoIncrementColumn(table, "VisitorId"); | ||||
|             SiteId = AddIntegerColumn(table, "SiteId"); | ||||
|             UserId = AddIntegerColumn(table, "UserId", true); | ||||
|             Visits = AddIntegerColumn(table, "Visits"); | ||||
|             IPAddress = AddStringColumn(table,"IPAddress", 50); | ||||
|             UserAgent = AddStringColumn(table, "UserAgent", 256); | ||||
|             Language = AddStringColumn(table, "Language", 50); | ||||
|             CreatedOn = AddDateTimeColumn(table, "CreatedOn"); | ||||
|             VisitedOn = AddDateTimeColumn(table, "VisitedOn"); | ||||
|  | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         public OperationBuilder<AddColumnOperation> VisitorId { get; private set; } | ||||
|  | ||||
|         public OperationBuilder<AddColumnOperation> SiteId { get; private set; } | ||||
|  | ||||
|         public OperationBuilder<AddColumnOperation> UserId { get; private set; } | ||||
|  | ||||
|         public OperationBuilder<AddColumnOperation> Visits { get; private set; } | ||||
|  | ||||
|         public OperationBuilder<AddColumnOperation> IPAddress { get; private set; } | ||||
|  | ||||
|         public OperationBuilder<AddColumnOperation> UserAgent { get; private set; } | ||||
|  | ||||
|         public OperationBuilder<AddColumnOperation> Language { get; private set; } | ||||
|  | ||||
|         public OperationBuilder<AddColumnOperation> CreatedOn { get; private set; } | ||||
|  | ||||
|         public OperationBuilder<AddColumnOperation> VisitedOn { get; private set; } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										29
									
								
								Oqtane.Server/Migrations/Tenant/03000102_AddVisitorTable.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								Oqtane.Server/Migrations/Tenant/03000102_AddVisitorTable.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| using Microsoft.EntityFrameworkCore.Infrastructure; | ||||
| using Microsoft.EntityFrameworkCore.Migrations; | ||||
| using Oqtane.Databases.Interfaces; | ||||
| using Oqtane.Migrations.EntityBuilders; | ||||
| using Oqtane.Repository; | ||||
|  | ||||
| namespace Oqtane.Migrations.Tenant | ||||
| { | ||||
|     [DbContext(typeof(TenantDBContext))] | ||||
|     [Migration("Tenant.03.00.01.02")] | ||||
|     public class AddVisitorTable : MultiDatabaseMigration | ||||
|     { | ||||
|         public AddVisitorTable(IDatabase database) : base(database) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         protected override void Up(MigrationBuilder migrationBuilder) | ||||
|         { | ||||
|             var visitorEntityBuilder = new VisitorEntityBuilder(migrationBuilder, ActiveDatabase); | ||||
|             visitorEntityBuilder.Create(); | ||||
|         } | ||||
|  | ||||
|         protected override void Down(MigrationBuilder migrationBuilder) | ||||
|         { | ||||
|             var visitorEntityBuilder = new VisitorEntityBuilder(migrationBuilder, ActiveDatabase); | ||||
|             visitorEntityBuilder.Drop(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,30 @@ | ||||
| using Microsoft.EntityFrameworkCore.Infrastructure; | ||||
| using Microsoft.EntityFrameworkCore.Migrations; | ||||
| using Oqtane.Databases.Interfaces; | ||||
| using Oqtane.Migrations.EntityBuilders; | ||||
| using Oqtane.Repository; | ||||
|  | ||||
| namespace Oqtane.Migrations.Tenant | ||||
| { | ||||
|     [DbContext(typeof(TenantDBContext))] | ||||
|     [Migration("Tenant.03.00.01.03")] | ||||
|     public class AddUrlMappingTable : MultiDatabaseMigration | ||||
|     { | ||||
|         public AddUrlMappingTable(IDatabase database) : base(database) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         protected override void Up(MigrationBuilder migrationBuilder) | ||||
|         { | ||||
|             var urlMappingEntityBuilder = new UrlMappingEntityBuilder(migrationBuilder, ActiveDatabase); | ||||
|             urlMappingEntityBuilder.Create(); | ||||
|             urlMappingEntityBuilder.AddIndex("IX_UrlMapping", new[] { "SiteId", "Url" }, true); | ||||
|         } | ||||
|  | ||||
|         protected override void Down(MigrationBuilder migrationBuilder) | ||||
|         { | ||||
|             var urlMappingEntityBuilder = new UrlMappingEntityBuilder(migrationBuilder, ActiveDatabase); | ||||
|             urlMappingEntityBuilder.Drop(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,35 @@ | ||||
| using Microsoft.EntityFrameworkCore.Infrastructure; | ||||
| using Microsoft.EntityFrameworkCore.Migrations; | ||||
| using Oqtane.Databases.Interfaces; | ||||
| using Oqtane.Migrations.EntityBuilders; | ||||
| using Oqtane.Repository; | ||||
|  | ||||
| namespace Oqtane.Migrations.Tenant | ||||
| { | ||||
|     [DbContext(typeof(TenantDBContext))] | ||||
|     [Migration("Tenant.03.00.01.04")] | ||||
|     public class AddSiteVisitorTracking : MultiDatabaseMigration | ||||
|     { | ||||
|         public AddSiteVisitorTracking(IDatabase database) : base(database) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         protected override void Up(MigrationBuilder migrationBuilder) | ||||
|         { | ||||
|             var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase); | ||||
|  | ||||
|             siteEntityBuilder.AddBooleanColumn("VisitorTracking", true); | ||||
|             siteEntityBuilder.UpdateColumn("VisitorTracking", "1", "bool", ""); | ||||
|             siteEntityBuilder.AddBooleanColumn("CaptureBrokenUrls", true); | ||||
|             siteEntityBuilder.UpdateColumn("CaptureBrokenUrls", "1", "bool", ""); | ||||
|         } | ||||
|  | ||||
|         protected override void Down(MigrationBuilder migrationBuilder) | ||||
|         { | ||||
|             var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase); | ||||
|  | ||||
|             siteEntityBuilder.DropColumn("VisitorTracking"); | ||||
|             siteEntityBuilder.DropColumn("CaptureBrokenUrls"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -22,7 +22,7 @@ | ||||
| <body> | ||||
|     @(Html.AntiForgeryToken()) | ||||
|     <app> | ||||
|         <component type="typeof(Oqtane.App)" render-mode="@Model.RenderMode" param-AntiForgeryToken="@Model.AntiForgeryToken" param-Runtime="@Model.Runtime" param-RenderMode="@Model.RenderMode.ToString()" /> | ||||
|         <component type="typeof(Oqtane.App)" render-mode="@Model.RenderMode" param-AntiForgeryToken="@Model.AntiForgeryToken" param-Runtime="@Model.Runtime" param-RenderMode="@Model.RenderMode.ToString()" param-VisitorId="@Model.VisitorId" /> | ||||
|     </app> | ||||
|  | ||||
|     <div id="blazor-error-ui"> | ||||
|  | ||||
| @ -14,6 +14,10 @@ using Microsoft.Extensions.Configuration; | ||||
| using Microsoft.AspNetCore.Mvc.Rendering; | ||||
| using Microsoft.AspNetCore.Antiforgery; | ||||
| using Microsoft.AspNetCore.Http.Extensions; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using Microsoft.Net.Http.Headers; | ||||
| using Microsoft.AspNetCore.Http; | ||||
| using System.Security.Claims; | ||||
|  | ||||
| namespace Oqtane.Pages | ||||
| { | ||||
| @ -26,8 +30,10 @@ namespace Oqtane.Pages | ||||
|         private readonly IAntiforgery _antiforgery; | ||||
|         private readonly ISiteRepository _sites; | ||||
|         private readonly IPageRepository _pages; | ||||
|         private readonly IUrlMappingRepository _urlMappings; | ||||
|         private readonly IVisitorRepository _visitors; | ||||
|  | ||||
|         public HostModel(IConfiguration configuration, ITenantManager tenantManager, ILocalizationManager localizationManager, ILanguageRepository languages, IAntiforgery antiforgery, ISiteRepository sites, IPageRepository pages) | ||||
|         public HostModel(IConfiguration configuration, ITenantManager tenantManager, ILocalizationManager localizationManager, ILanguageRepository languages, IAntiforgery antiforgery, ISiteRepository sites, IPageRepository pages, IUrlMappingRepository urlMappings, IVisitorRepository visitors) | ||||
|         { | ||||
|             _configuration = configuration; | ||||
|             _tenantManager = tenantManager; | ||||
| @ -36,11 +42,14 @@ namespace Oqtane.Pages | ||||
|             _antiforgery = antiforgery; | ||||
|             _sites = sites; | ||||
|             _pages = pages; | ||||
|             _urlMappings = urlMappings; | ||||
|             _visitors = visitors; | ||||
|         } | ||||
|  | ||||
|         public string AntiForgeryToken = ""; | ||||
|         public string Runtime = "Server"; | ||||
|         public RenderMode RenderMode = RenderMode.Server; | ||||
|         public int VisitorId = -1; | ||||
|         public string HeadResources = ""; | ||||
|         public string BodyResources = ""; | ||||
|         public string Title = ""; | ||||
| @ -48,7 +57,7 @@ namespace Oqtane.Pages | ||||
|         public string PWAScript = ""; | ||||
|         public string ThemeType = ""; | ||||
|  | ||||
|         public void OnGet() | ||||
|         public IActionResult OnGet() | ||||
|         { | ||||
|             AntiForgeryToken = _antiforgery.GetAndStoreTokens(HttpContext).RequestToken; | ||||
|  | ||||
| @ -92,6 +101,11 @@ namespace Oqtane.Pages | ||||
|                         Title = site.Name; | ||||
|                         ThemeType = site.DefaultThemeType; | ||||
|  | ||||
|                         if (site.VisitorTracking) | ||||
|                         { | ||||
|                             TrackVisitor(site.SiteId); | ||||
|                         } | ||||
|  | ||||
|                         var page = _pages.GetPage(route.PagePath, site.SiteId); | ||||
|                         if (page != null) | ||||
|                         { | ||||
| @ -111,6 +125,37 @@ namespace Oqtane.Pages | ||||
|                                 ThemeType = page.ThemeType; | ||||
|                             } | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             // page does not exist | ||||
|                             var url = route.SiteUrl + "/" + route.PagePath; | ||||
|                             var urlMapping = _urlMappings.GetUrlMapping(site.SiteId, url); | ||||
|                             if (urlMapping == null) | ||||
|                             { | ||||
|                                 if (site.CaptureBrokenUrls) | ||||
|                                 { | ||||
|                                     urlMapping = new UrlMapping(); | ||||
|                                     urlMapping.SiteId = site.SiteId; | ||||
|                                     urlMapping.Url = url; | ||||
|                                     urlMapping.MappedUrl = ""; | ||||
|                                     urlMapping.Requests = 1; | ||||
|                                     urlMapping.CreatedOn = DateTime.UtcNow; | ||||
|                                     urlMapping.RequestedOn = DateTime.UtcNow; | ||||
|                                     _urlMappings.AddUrlMapping(urlMapping); | ||||
|                                 } | ||||
|                             } | ||||
|                             else | ||||
|                             { | ||||
|                                 urlMapping.Requests += 1; | ||||
|                                 urlMapping.RequestedOn = DateTime.UtcNow; | ||||
|                                 _urlMappings.UpdateUrlMapping(urlMapping); | ||||
|  | ||||
|                                 if (!string.IsNullOrEmpty(urlMapping.MappedUrl)) | ||||
|                                 { | ||||
|                                     return RedirectPermanent(urlMapping.MappedUrl); | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     // include global resources | ||||
| @ -139,6 +184,64 @@ namespace Oqtane.Pages | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             return Page(); | ||||
|         } | ||||
|  | ||||
|         private void TrackVisitor(int SiteId) | ||||
|         { | ||||
|             var VisitorCookie = "APP_VISITOR_" + SiteId.ToString(); | ||||
|             if (!int.TryParse(Request.Cookies[VisitorCookie], out VisitorId)) | ||||
|             { | ||||
|                 var visitor = new Visitor(); | ||||
|                 visitor.SiteId = SiteId; | ||||
|                 visitor.IPAddress = HttpContext.Connection.RemoteIpAddress.ToString(); | ||||
|                 visitor.UserAgent = Request.Headers[HeaderNames.UserAgent]; | ||||
|                 visitor.Language = Request.Headers[HeaderNames.AcceptLanguage]; | ||||
|                 if (visitor.Language.Contains(",")) | ||||
|                 { | ||||
|                     visitor.Language = visitor.Language.Substring(0, visitor.Language.IndexOf(",")); | ||||
|                 } | ||||
|                 visitor.UserId = null; | ||||
|                 visitor.Visits = 1; | ||||
|                 visitor.CreatedOn = DateTime.UtcNow; | ||||
|                 visitor.VisitedOn = DateTime.UtcNow; | ||||
|                 visitor = _visitors.AddVisitor(visitor); | ||||
|  | ||||
|                 Response.Cookies.Append( | ||||
|                     VisitorCookie, | ||||
|                     visitor.VisitorId.ToString(), | ||||
|                     new CookieOptions() | ||||
|                     { | ||||
|                         Expires = DateTimeOffset.UtcNow.AddYears(1), | ||||
|                         IsEssential = true | ||||
|                     } | ||||
|                 ); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 var visitor = _visitors.GetVisitor(VisitorId); | ||||
|                 if (visitor != null) | ||||
|                 { | ||||
|                     visitor.IPAddress = HttpContext.Connection.RemoteIpAddress.ToString(); | ||||
|                     visitor.UserAgent = Request.Headers[HeaderNames.UserAgent]; | ||||
|                     visitor.Language = Request.Headers[HeaderNames.AcceptLanguage]; | ||||
|                     if (visitor.Language.Contains(",")) | ||||
|                     { | ||||
|                         visitor.Language = visitor.Language.Substring(0, visitor.Language.IndexOf(",")); | ||||
|                     } | ||||
|                     if (User.HasClaim(item => item.Type == ClaimTypes.PrimarySid)) | ||||
|                     { | ||||
|                         visitor.UserId = int.Parse(User.Claims.First(item => item.Type == ClaimTypes.PrimarySid).Value); | ||||
|                     } | ||||
|                     visitor.Visits += 1; | ||||
|                     visitor.VisitedOn = DateTime.UtcNow; | ||||
|                     _visitors.UpdateVisitor(visitor); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     Response.Cookies.Delete(VisitorCookie); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private string CreatePWAScript(Alias alias, Site site, Route route) | ||||
|  | ||||
| @ -29,5 +29,7 @@ namespace Oqtane.Repository | ||||
|         public virtual DbSet<Folder> Folder { get; set; } | ||||
|         public virtual DbSet<File> File { get; set; } | ||||
|         public virtual DbSet<Language> Language { get; set; } | ||||
|         public virtual DbSet<Visitor> Visitor { get; set; } | ||||
|         public virtual DbSet<UrlMapping> UrlMapping { get; set; } | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										17
									
								
								Oqtane.Server/Repository/Interfaces/IUrlMappingRepository.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								Oqtane.Server/Repository/Interfaces/IUrlMappingRepository.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using Oqtane.Models; | ||||
|  | ||||
| namespace Oqtane.Repository | ||||
| { | ||||
|     public interface IUrlMappingRepository | ||||
|     { | ||||
|         IEnumerable<UrlMapping> GetUrlMappings(int siteId, bool isMapped); | ||||
|         UrlMapping AddUrlMapping(UrlMapping urlMapping); | ||||
|         UrlMapping UpdateUrlMapping(UrlMapping urlMapping); | ||||
|         UrlMapping GetUrlMapping(int urlMappingId); | ||||
|         UrlMapping GetUrlMapping(int urlMappingId, bool tracking); | ||||
|         UrlMapping GetUrlMapping(int siteId, string url); | ||||
|         void DeleteUrlMapping(int urlMappingId); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										15
									
								
								Oqtane.Server/Repository/Interfaces/IVisitorRepository.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								Oqtane.Server/Repository/Interfaces/IVisitorRepository.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using Oqtane.Models; | ||||
|  | ||||
| namespace Oqtane.Repository | ||||
| { | ||||
|     public interface IVisitorRepository | ||||
|     { | ||||
|         IEnumerable<Visitor> GetVisitors(int siteId, DateTime fromDate); | ||||
|         Visitor AddVisitor(Visitor visitor); | ||||
|         Visitor UpdateVisitor(Visitor visitor); | ||||
|         Visitor GetVisitor(int visitorId); | ||||
|         void DeleteVisitor(int visitorId); | ||||
|     } | ||||
| } | ||||
| @ -615,13 +615,70 @@ namespace Oqtane.Repository | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|             pageTemplates.Add(new PageTemplate | ||||
|             { | ||||
|                 Name = "Url Mappings", | ||||
|                 Parent = "Admin", | ||||
|                 Order = 15, | ||||
|                 Path = "admin/urlmappings", | ||||
|                 Icon = Icons.LinkBroken, | ||||
|                 IsNavigation = true, | ||||
|                 IsPersonalizable = false, | ||||
|                 PagePermissions = new List<Permission> | ||||
|                 { | ||||
|                     new Permission(PermissionNames.View, RoleNames.Admin, true), | ||||
|                     new Permission(PermissionNames.Edit, RoleNames.Admin, true) | ||||
|                 }.EncodePermissions(), | ||||
|                 PageTemplateModules = new List<PageTemplateModule> | ||||
|                 { | ||||
|                     new PageTemplateModule | ||||
|                     { | ||||
|                         ModuleDefinitionName = typeof(Oqtane.Modules.Admin.UrlMappings.Index).ToModuleDefinitionName(), Title = "Url Mappings", Pane = PaneNames.Admin, | ||||
|                         ModulePermissions = new List<Permission> | ||||
|                         { | ||||
|                             new Permission(PermissionNames.View, RoleNames.Admin, true), | ||||
|                             new Permission(PermissionNames.Edit, RoleNames.Admin, true) | ||||
|                         }.EncodePermissions(), | ||||
|                         Content = "" | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             pageTemplates.Add(new PageTemplate | ||||
|             { | ||||
|                 Name = "Visitor Management", | ||||
|                 Parent = "Admin", | ||||
|                 Order = 17, | ||||
|                 Path = "admin/visitors", | ||||
|                 Icon = Icons.Eye, | ||||
|                 IsNavigation = true, | ||||
|                 IsPersonalizable = false, | ||||
|                 PagePermissions = new List<Permission> | ||||
|                 { | ||||
|                     new Permission(PermissionNames.View, RoleNames.Admin, true), | ||||
|                     new Permission(PermissionNames.Edit, RoleNames.Admin, true) | ||||
|                 }.EncodePermissions(), | ||||
|                 PageTemplateModules = new List<PageTemplateModule> | ||||
|                 { | ||||
|                     new PageTemplateModule | ||||
|                     { | ||||
|                         ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Visitors.Index).ToModuleDefinitionName(), Title = "Visitor Management", Pane = PaneNames.Admin, | ||||
|                         ModulePermissions = new List<Permission> | ||||
|                         { | ||||
|                             new Permission(PermissionNames.View, RoleNames.Admin, true), | ||||
|                             new Permission(PermissionNames.Edit, RoleNames.Admin, true) | ||||
|                         }.EncodePermissions(), | ||||
|                         Content = "" | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             // host pages | ||||
|             pageTemplates.Add(new PageTemplate | ||||
|             { | ||||
|                 Name = "Event Log", | ||||
|                 Parent = "Admin", | ||||
|                 Order = 15, | ||||
|                 Order = 19, | ||||
|                 Path = "admin/log", | ||||
|                 Icon = Icons.MagnifyingGlass, | ||||
|                 IsNavigation = false, | ||||
| @ -649,7 +706,7 @@ namespace Oqtane.Repository | ||||
|             { | ||||
|                 Name = "Site Management", | ||||
|                 Parent = "Admin", | ||||
|                 Order = 17, | ||||
|                 Order = 21, | ||||
|                 Path = "admin/sites", | ||||
|                 Icon = Icons.Globe, | ||||
|                 IsNavigation = false, | ||||
| @ -677,7 +734,7 @@ namespace Oqtane.Repository | ||||
|             { | ||||
|                 Name = "Module Management", | ||||
|                 Parent = "Admin", | ||||
|                 Order = 19, | ||||
|                 Order = 23, | ||||
|                 Path = "admin/modules", | ||||
|                 Icon = Icons.Browser, | ||||
|                 IsNavigation = false, | ||||
| @ -705,7 +762,7 @@ namespace Oqtane.Repository | ||||
|             { | ||||
|                 Name = "Theme Management", | ||||
|                 Parent = "Admin", | ||||
|                 Order = 21, | ||||
|                 Order = 25, | ||||
|                 Path = "admin/themes", | ||||
|                 Icon = Icons.Brush, | ||||
|                 IsNavigation = false, | ||||
| @ -733,7 +790,7 @@ namespace Oqtane.Repository | ||||
|             { | ||||
|                 Name = "Language Management", | ||||
|                 Parent = "Admin", | ||||
|                 Order = 23, | ||||
|                 Order = 27, | ||||
|                 Path = "admin/languages", | ||||
|                 Icon = Icons.Text, | ||||
|                 IsNavigation = false, | ||||
| @ -765,7 +822,7 @@ namespace Oqtane.Repository | ||||
|             { | ||||
|                 Name = "Scheduled Jobs", | ||||
|                 Parent = "Admin", | ||||
|                 Order = 25, | ||||
|                 Order = 29, | ||||
|                 Path = "admin/jobs", | ||||
|                 Icon = Icons.Timer, | ||||
|                 IsNavigation = false, | ||||
| @ -793,7 +850,7 @@ namespace Oqtane.Repository | ||||
|             { | ||||
|                 Name = "Sql Management", | ||||
|                 Parent = "Admin", | ||||
|                 Order = 27, | ||||
|                 Order = 31, | ||||
|                 Path = "admin/sql", | ||||
|                 Icon = Icons.Spreadsheet, | ||||
|                 IsNavigation = false, | ||||
| @ -821,7 +878,7 @@ namespace Oqtane.Repository | ||||
|             { | ||||
|                 Name = "System Info", | ||||
|                 Parent = "Admin", | ||||
|                 Order = 29, | ||||
|                 Order = 33, | ||||
|                 Path = "admin/system", | ||||
|                 Icon = Icons.MedicalCross, | ||||
|                 IsNavigation = false, | ||||
| @ -849,7 +906,7 @@ namespace Oqtane.Repository | ||||
|             { | ||||
|                 Name = "System Update", | ||||
|                 Parent = "Admin", | ||||
|                 Order = 31, | ||||
|                 Order = 35, | ||||
|                 Path = "admin/update", | ||||
|                 Icon = Icons.Aperture, | ||||
|                 IsNavigation = false, | ||||
|  | ||||
							
								
								
									
										73
									
								
								Oqtane.Server/Repository/UrlMappingRepository.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								Oqtane.Server/Repository/UrlMappingRepository.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,73 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using Oqtane.Models; | ||||
|  | ||||
| namespace Oqtane.Repository | ||||
| { | ||||
|     public class UrlMappingRepository : IUrlMappingRepository | ||||
|     { | ||||
|         private TenantDBContext _db; | ||||
|  | ||||
|         public UrlMappingRepository(TenantDBContext context) | ||||
|         { | ||||
|             _db = context; | ||||
|         } | ||||
|              | ||||
|         public IEnumerable<UrlMapping> GetUrlMappings(int siteId, bool isMapped) | ||||
|         { | ||||
|             if (isMapped) | ||||
|             { | ||||
|                 return _db.UrlMapping.Where(item => item.SiteId == siteId && !string.IsNullOrEmpty(item.MappedUrl)).Take(200); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 return _db.UrlMapping.Where(item => item.SiteId == siteId && string.IsNullOrEmpty(item.MappedUrl)).Take(200); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public UrlMapping AddUrlMapping(UrlMapping urlMapping) | ||||
|         { | ||||
|             _db.UrlMapping.Add(urlMapping); | ||||
|             _db.SaveChanges(); | ||||
|             return urlMapping; | ||||
|         } | ||||
|  | ||||
|         public UrlMapping UpdateUrlMapping(UrlMapping urlMapping) | ||||
|         { | ||||
|             _db.Entry(urlMapping).State = EntityState.Modified; | ||||
|             _db.SaveChanges(); | ||||
|             return urlMapping; | ||||
|         } | ||||
|  | ||||
|         public UrlMapping GetUrlMapping(int urlMappingId) | ||||
|         { | ||||
|             return GetUrlMapping(urlMappingId, true); | ||||
|         } | ||||
|  | ||||
|         public UrlMapping GetUrlMapping(int urlMappingId, bool tracking) | ||||
|         { | ||||
|             if (tracking) | ||||
|             { | ||||
|                 return _db.UrlMapping.Find(urlMappingId); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 return _db.UrlMapping.AsNoTracking().FirstOrDefault(item => item.UrlMappingId == urlMappingId); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public UrlMapping GetUrlMapping(int siteId, string url) | ||||
|         { | ||||
|             return _db.UrlMapping.Where(item => item.SiteId == siteId && item.Url == url).FirstOrDefault(); | ||||
|         } | ||||
|  | ||||
|         public void DeleteUrlMapping(int urlMappingId) | ||||
|         { | ||||
|             UrlMapping urlMapping = _db.UrlMapping.Find(urlMappingId); | ||||
|             _db.UrlMapping.Remove(urlMapping); | ||||
|             _db.SaveChanges(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										51
									
								
								Oqtane.Server/Repository/VisitorRepository.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								Oqtane.Server/Repository/VisitorRepository.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using Oqtane.Models; | ||||
|  | ||||
| namespace Oqtane.Repository | ||||
| { | ||||
|     public class VisitorRepository : IVisitorRepository | ||||
|     { | ||||
|         private TenantDBContext _db; | ||||
|  | ||||
|         public VisitorRepository(TenantDBContext context) | ||||
|         { | ||||
|             _db = context; | ||||
|         } | ||||
|              | ||||
|         public IEnumerable<Visitor> GetVisitors(int siteId, DateTime fromDate) | ||||
|         { | ||||
|             return _db.Visitor.AsNoTracking() | ||||
|                 .Include(item => item.User) // eager load users | ||||
|                 .Where(item => item.SiteId == siteId && item.VisitedOn >= fromDate); | ||||
|         } | ||||
|  | ||||
|         public Visitor AddVisitor(Visitor visitor) | ||||
|         { | ||||
|             _db.Visitor.Add(visitor); | ||||
|             _db.SaveChanges(); | ||||
|             return visitor; | ||||
|         } | ||||
|  | ||||
|         public Visitor UpdateVisitor(Visitor visitor) | ||||
|         { | ||||
|             _db.Entry(visitor).State = EntityState.Modified; | ||||
|             _db.SaveChanges(); | ||||
|             return visitor; | ||||
|         } | ||||
|  | ||||
|         public Visitor GetVisitor(int visitorId) | ||||
|         { | ||||
|             return _db.Visitor.Find(visitorId); | ||||
|         } | ||||
|  | ||||
|         public void DeleteVisitor(int visitorId) | ||||
|         { | ||||
|             Visitor visitor = _db.Visitor.Find(visitorId); | ||||
|             _db.Visitor.Remove(visitor); | ||||
|             _db.SaveChanges(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Shaun Walker
					Shaun Walker