add support for visitor tracking
This commit is contained in:
parent
e47690dd52
commit
d0da1f43a9
@ -1,7 +1,12 @@
|
|||||||
@namespace Oqtane.Components
|
@namespace Oqtane.Components
|
||||||
|
@using System.Net
|
||||||
|
@using System.Security.Claims
|
||||||
@using Microsoft.AspNetCore.Http
|
@using Microsoft.AspNetCore.Http
|
||||||
@using Microsoft.AspNetCore.Http.Extensions
|
@using Microsoft.AspNetCore.Http.Extensions
|
||||||
@using Microsoft.AspNetCore.Antiforgery
|
@using Microsoft.AspNetCore.Antiforgery
|
||||||
|
@using Microsoft.AspNetCore.Localization
|
||||||
|
@using Microsoft.Net.Http.Headers
|
||||||
|
@using Microsoft.Extensions.Primitives
|
||||||
@using Oqtane.Client
|
@using Oqtane.Client
|
||||||
@using Oqtane.Client.Utilities
|
@using Oqtane.Client.Utilities
|
||||||
@using Oqtane.Repository
|
@using Oqtane.Repository
|
||||||
@ -10,20 +15,20 @@
|
|||||||
@using Oqtane.Models
|
@using Oqtane.Models
|
||||||
@using Oqtane.Shared
|
@using Oqtane.Shared
|
||||||
@using Oqtane.Themes
|
@using Oqtane.Themes
|
||||||
@using System.Net
|
|
||||||
@using Microsoft.AspNetCore.Localization
|
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IAntiforgery Antiforgery;
|
@inject IAntiforgery Antiforgery
|
||||||
@inject IConfigManager ConfigManager;
|
@inject IConfigManager ConfigManager
|
||||||
@inject ITenantManager TenantManager;
|
@inject ITenantManager TenantManager
|
||||||
@inject ISiteRepository SiteRepository;
|
@inject ISiteRepository SiteRepository
|
||||||
@inject IPageRepository PageRepository;
|
@inject IPageRepository PageRepository
|
||||||
@inject IThemeRepository ThemeRepository;
|
@inject IThemeRepository ThemeRepository
|
||||||
@inject ILanguageRepository LanguageRepository;
|
@inject ILanguageRepository LanguageRepository
|
||||||
@inject IServerStateManager ServerStateManager;
|
@inject IServerStateManager ServerStateManager
|
||||||
@inject ILocalizationManager LocalizationManager;
|
@inject ILocalizationManager LocalizationManager
|
||||||
@inject IAliasRepository AliasRepository;
|
@inject IAliasRepository AliasRepository
|
||||||
@inject IUrlMappingRepository UrlMappingRepository;
|
@inject IUrlMappingRepository UrlMappingRepository
|
||||||
|
@inject ISettingRepository SettingRepository
|
||||||
|
@inject IVisitorRepository VisitorRepository
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="@_language">
|
<html lang="@_language">
|
||||||
@ -56,11 +61,11 @@
|
|||||||
{
|
{
|
||||||
@if (_renderMode == "Interactive")
|
@if (_renderMode == "Interactive")
|
||||||
{
|
{
|
||||||
<Routes AntiForgeryToken="@_antiForgeryToken" Runtime="Server" RenderMode="PreRendered" VisitorId="-1" RemoteIPAddress="@_remoteIPAddress" AuthorizationToken="" @rendermode="@RenderModes.GetInteractiveRenderMode((_renderMode + _interactiveRenderMode), _prerender)" />
|
<Routes AntiForgeryToken="@_antiForgeryToken" Runtime="Server" RenderMode="PreRendered" VisitorId="@_visitorId" RemoteIPAddress="@_remoteIPAddress" AuthorizationToken="" @rendermode="@RenderModes.GetInteractiveRenderMode((_renderMode + _interactiveRenderMode), _prerender)" />
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<Routes AntiForgeryToken="@_antiForgeryToken" Runtime="Server" RenderMode="PreRendered" VisitorId="-1" RemoteIPAddress="@_remoteIPAddress" AuthorizationToken="" />
|
<Routes AntiForgeryToken="@_antiForgeryToken" Runtime="Server" RenderMode="PreRendered" VisitorId="@_visitorId" RemoteIPAddress="@_remoteIPAddress" AuthorizationToken="" />
|
||||||
}
|
}
|
||||||
|
|
||||||
<script src="js/interop.js"></script>
|
<script src="js/interop.js"></script>
|
||||||
@ -96,6 +101,7 @@
|
|||||||
private string _PWAScript = "";
|
private string _PWAScript = "";
|
||||||
private string _reconnectScript = "";
|
private string _reconnectScript = "";
|
||||||
private string _message = "";
|
private string _message = "";
|
||||||
|
private int _visitorId = -1;
|
||||||
|
|
||||||
// CascadingParameter is required to access HttpContext
|
// CascadingParameter is required to access HttpContext
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
@ -143,10 +149,10 @@
|
|||||||
HandlePageNotFound(site, page, route);
|
HandlePageNotFound(site, page, route);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (site.VisitorTracking)
|
if (site.VisitorTracking)
|
||||||
// {
|
{
|
||||||
// TrackVisitor(site.SiteId);
|
TrackVisitor(site.SiteId);
|
||||||
// }
|
}
|
||||||
|
|
||||||
// get jwt token for downstream APIs
|
// get jwt token for downstream APIs
|
||||||
// if (User.Identity.IsAuthenticated)
|
// if (User.Identity.IsAuthenticated)
|
||||||
@ -279,6 +285,137 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void TrackVisitor(int SiteId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// get request attributes
|
||||||
|
string useragent = (Context.Request.Headers[HeaderNames.UserAgent] != StringValues.Empty) ? Context.Request.Headers[HeaderNames.UserAgent] : "(none)";
|
||||||
|
useragent = (useragent.Length > 256) ? useragent.Substring(0, 256) : useragent;
|
||||||
|
string language = (Context.Request.Headers[HeaderNames.AcceptLanguage] != StringValues.Empty) ? Context.Request.Headers[HeaderNames.AcceptLanguage] : "";
|
||||||
|
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
|
||||||
|
string filter = Constants.DefaultVisitorFilter;
|
||||||
|
var settings = SettingRepository.GetSettings(EntityNames.Site, SiteId);
|
||||||
|
if (settings.Any(item => item.SettingName == "VisitorFilter"))
|
||||||
|
{
|
||||||
|
filter = settings.First(item => item.SettingName == "VisitorFilter").SettingValue;
|
||||||
|
}
|
||||||
|
foreach (string term in filter.ToLower().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(sValue => sValue.Trim()).ToArray())
|
||||||
|
{
|
||||||
|
if (_remoteIPAddress.ToLower().Contains(term) || useragent.ToLower().Contains(term) || language.ToLower().Contains(term))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get other request attributes
|
||||||
|
string url = Context.Request.GetEncodedUrl();
|
||||||
|
string referrer = (Context.Request.Headers[HeaderNames.Referer] != StringValues.Empty) ? Context.Request.Headers[HeaderNames.Referer] : "";
|
||||||
|
int? userid = null;
|
||||||
|
if (Context.User.HasClaim(item => item.Type == ClaimTypes.NameIdentifier))
|
||||||
|
{
|
||||||
|
userid = int.Parse(Context.User.Claims.First(item => item.Type == ClaimTypes.NameIdentifier).Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if cookie already exists
|
||||||
|
Visitor visitor = null;
|
||||||
|
bool addcookie = false;
|
||||||
|
var VisitorCookie = Constants.VisitorCookiePrefix + SiteId.ToString();
|
||||||
|
if (!int.TryParse(Context.Request.Cookies[VisitorCookie], out _visitorId))
|
||||||
|
{
|
||||||
|
// if enabled use IP Address correlation
|
||||||
|
_visitorId = -1;
|
||||||
|
bool correlate = true;
|
||||||
|
if (settings.Any(item => item.SettingName == "VisitorCorrelation"))
|
||||||
|
{
|
||||||
|
correlate = bool.Parse(settings.First(item => item.SettingName == "VisitorCorrelation").SettingValue);
|
||||||
|
}
|
||||||
|
if (correlate)
|
||||||
|
{
|
||||||
|
visitor = VisitorRepository.GetVisitor(SiteId, _remoteIPAddress);
|
||||||
|
if (visitor != null)
|
||||||
|
{
|
||||||
|
_visitorId = visitor.VisitorId;
|
||||||
|
addcookie = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_visitorId == -1)
|
||||||
|
{
|
||||||
|
// create new visitor
|
||||||
|
visitor = new Visitor();
|
||||||
|
visitor.SiteId = SiteId;
|
||||||
|
visitor.IPAddress = _remoteIPAddress;
|
||||||
|
visitor.UserAgent = useragent;
|
||||||
|
visitor.Language = language;
|
||||||
|
visitor.Url = url;
|
||||||
|
visitor.Referrer = referrer;
|
||||||
|
visitor.UserId = userid;
|
||||||
|
visitor.Visits = 1;
|
||||||
|
visitor.CreatedOn = DateTime.UtcNow;
|
||||||
|
visitor.VisitedOn = DateTime.UtcNow;
|
||||||
|
visitor = VisitorRepository.AddVisitor(visitor);
|
||||||
|
_visitorId = visitor.VisitorId;
|
||||||
|
addcookie = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (visitor == null)
|
||||||
|
{
|
||||||
|
// get visitor if it was not previously loaded
|
||||||
|
visitor = VisitorRepository.GetVisitor(_visitorId);
|
||||||
|
}
|
||||||
|
if (visitor != null)
|
||||||
|
{
|
||||||
|
// update visitor
|
||||||
|
visitor.IPAddress = _remoteIPAddress;
|
||||||
|
visitor.UserAgent = useragent;
|
||||||
|
visitor.Language = language;
|
||||||
|
visitor.Url = url;
|
||||||
|
if (!string.IsNullOrEmpty(referrer))
|
||||||
|
{
|
||||||
|
visitor.Referrer = referrer;
|
||||||
|
}
|
||||||
|
if (userid != null)
|
||||||
|
{
|
||||||
|
visitor.UserId = userid;
|
||||||
|
}
|
||||||
|
visitor.Visits += 1;
|
||||||
|
visitor.VisitedOn = DateTime.UtcNow;
|
||||||
|
VisitorRepository.UpdateVisitor(visitor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// remove cookie if VisitorId does not exist
|
||||||
|
Context.Response.Cookies.Delete(VisitorCookie);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// append cookie
|
||||||
|
if (addcookie)
|
||||||
|
{
|
||||||
|
Context.Response.Cookies.Append(
|
||||||
|
VisitorCookie,
|
||||||
|
_visitorId.ToString(),
|
||||||
|
new CookieOptions()
|
||||||
|
{
|
||||||
|
Expires = DateTimeOffset.UtcNow.AddYears(1),
|
||||||
|
IsEssential = true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// error tracking visitor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private string CreatePWAScript(Alias alias, Site site, Route route)
|
private string CreatePWAScript(Alias alias, Site site, Route route)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
|
Reference in New Issue
Block a user