@namespace Oqtane.Components @using System.Net @using System.Security.Claims @using Microsoft.AspNetCore.Http @using Microsoft.AspNetCore.Http.Extensions @using Microsoft.AspNetCore.Antiforgery @using Microsoft.AspNetCore.Localization @using Microsoft.Net.Http.Headers @using Microsoft.Extensions.Primitives @using Oqtane.Client @using Oqtane.UI @using Oqtane.Repository @using Oqtane.Infrastructure @using Oqtane.Security @using Oqtane.Models @using Oqtane.Shared @using Oqtane.Themes @using Oqtane.Extensions @inject NavigationManager NavigationManager @inject IAntiforgery Antiforgery @inject IConfigManager ConfigManager @inject ITenantManager TenantManager @inject ISiteService SiteService @inject IPageRepository PageRepository @inject IThemeRepository ThemeRepository @inject ILanguageRepository LanguageRepository @inject IServerStateManager ServerStateManager @inject ILocalizationManager LocalizationManager @inject IAliasRepository AliasRepository @inject IUrlMappingRepository UrlMappingRepository @inject IVisitorRepository VisitorRepository @inject IJwtManager JwtManager @if (_pageState != null) { @if (!string.IsNullOrEmpty(_PWAScript)) { } @((MarkupString)_styleSheets) @if (_renderMode == RenderModes.Static) { } else { } @((MarkupString)_headResources) @if (string.IsNullOrEmpty(_message)) { @if (_renderMode == RenderModes.Static) { } else { } @if (!string.IsNullOrEmpty(_reconnectScript)) { @((MarkupString)_reconnectScript) } @if (!string.IsNullOrEmpty(_PWAScript)) { @((MarkupString)_PWAScript) } @((MarkupString)_bodyResources) } else {
@_message
} } @code { private string _renderMode = RenderModes.Interactive; private string _runtime = Runtimes.Server; private bool _prerender = true; private int _visitorId = -1; private string _remoteIPAddress = ""; private string _authorizationToken = ""; private string _language = "en"; private string _antiForgeryToken = ""; private string _headResources = ""; private string _bodyResources = ""; private string _styleSheets = ""; private string _PWAScript = ""; private string _reconnectScript = ""; private string _message = ""; private PageState _pageState; // CascadingParameter is required to access HttpContext [CascadingParameter] HttpContext Context { get; set; } protected override async Task OnInitializedAsync() { _antiForgeryToken = Antiforgery.GetAndStoreTokens(Context).RequestToken; _remoteIPAddress = Context.Connection.RemoteIpAddress?.ToString() ?? ""; // if framework is installed if (ConfigManager.IsInstalled()) { var alias = TenantManager.GetAlias(); if (alias != null) { var url = WebUtility.UrlDecode(Context.Request.GetEncodedUrl()); if (!alias.IsDefault) { HandleDefaultAliasRedirect(alias, url); } var site = await SiteService.GetSiteAsync(alias.SiteId); if (site != null && (!site.IsDeleted || url.Contains("admin/site")) && site.RenderMode != RenderModes.Headless) { _renderMode = site.RenderMode; _runtime = site.Runtime; _prerender = site.Prerender; Route route = new Route(url, alias.Path); var page = PageRepository.GetPage(route.PagePath, site.SiteId); if (page == null && route.PagePath == "" && site.HomePageId != null) { page = PageRepository.GetPage(site.HomePageId.Value); } if (page == null || page.IsDeleted) { HandlePageNotFound(site, page, route); } if (site.VisitorTracking) { TrackVisitor(site.SiteId); } // get jwt token for downstream APIs if (Context.User.Identity.IsAuthenticated) { CreateJwtToken(alias); } // stylesheets var themes = ThemeRepository.GetThemes().ToList(); var resources = new List(); if (string.IsNullOrEmpty(page.ThemeType)) { page.ThemeType = site.DefaultThemeType; } var theme = themes.FirstOrDefault(item => item.Themes.Any(item => item.TypeName == page.ThemeType)); if (theme?.Resources != null) { resources.AddRange(theme.Resources); } var type = Type.GetType(page.ThemeType); if (type != null) { var obj = Activator.CreateInstance(type) as IThemeControl; if (obj?.Resources != null) { resources.AddRange(obj.Resources); } } ManageStyleSheets(resources, alias, theme.ThemeName); if (_renderMode == RenderModes.Static) { ManageScripts(resources, alias); } // scripts if (_renderMode == RenderModes.Interactive && _runtime == Runtimes.Server) { _reconnectScript = CreateReconnectScript(); } if (site.PwaIsEnabled && site.PwaAppIconFileId != null && site.PwaSplashIconFileId != null) { _PWAScript = CreatePWAScript(alias, site, route); } _headResources += ParseScripts(site.HeadContent); _bodyResources += ParseScripts(site.BodyContent); var scripts = ServerStateManager.GetServerState(alias.SiteKey).Scripts; foreach (var script in scripts) { AddScript(script, alias); } // set culture if not specified string culture = Context.Request.Cookies[CookieRequestCultureProvider.DefaultCookieName]; if (culture == null) { // get default language for site var languages = LanguageRepository.GetLanguages(alias.SiteId); if (languages.Any()) { // use default language if specified otherwise use first language in collection culture = (languages.Where(l => l.IsDefault).SingleOrDefault() ?? languages.First()).Code; } else { culture = LocalizationManager.GetDefaultCulture(); } SetLocalizationCookie(culture); } // set language for page if (!string.IsNullOrEmpty(culture)) { // localization cookie value in form of c=en|uic=en _language = culture.Split('|')[0]; _language = _language.Replace("c=", ""); } // create initial PageState _pageState = new PageState { Alias = alias, Site = site, Page = page, User = null, Uri = new Uri(url, UriKind.Absolute), Route = route, QueryString = Utilities.ParseQueryString(route.Query), UrlParameters = route.UrlParameters, ModuleId = -1, Action = "", EditMode = false, LastSyncDate = DateTime.MinValue, RenderMode = _renderMode, Runtime = (Shared.Runtime)Enum.Parse(typeof(Shared.Runtime), _runtime), VisitorId = _visitorId, RemoteIPAddress = _remoteIPAddress, ReturnUrl = "", IsInternalNavigation = false, RenderId = Guid.NewGuid(), Refresh = true }; } else { _message = "Site Is Disabled"; } } else { _message = "Site Not Configured Correctly - No Matching Alias Exists For Host Name"; } } } private void HandleDefaultAliasRedirect(Alias alias, string url) { // get aliases for site and tenant var aliases = AliasRepository.GetAliases().Where(item => item.TenantId == alias.TenantId && item.SiteId == alias.SiteId); // get first default alias var defaultAlias = aliases.Where(item => item.IsDefault).FirstOrDefault(); if (defaultAlias != null) { // redirect to default alias NavigationManager.NavigateTo(url.Replace(alias.Name, defaultAlias.Name), true); } else // no default alias specified - use first alias { defaultAlias = aliases.FirstOrDefault(); if (defaultAlias != null && alias.Name.Trim() != defaultAlias.Name.Trim()) { // redirect to first alias NavigationManager.NavigateTo(url.Replace(alias.Name, defaultAlias.Name), true); } } } private void HandlePageNotFound(Site site, Page page, Route route) { // page not found - look for url mapping var urlMapping = UrlMappingRepository.GetUrlMapping(site.SiteId, route.PagePath); if (urlMapping != null && !string.IsNullOrEmpty(urlMapping.MappedUrl)) { // redirect to mapped url var url = (urlMapping.MappedUrl.StartsWith("http")) ? urlMapping.MappedUrl : route.SiteUrl + "/" + urlMapping.MappedUrl; NavigationManager.NavigateTo(url, true); } else // no url mapping exists { if (route.PagePath != "404") { // redirect to 404 page NavigationManager.NavigateTo(route.SiteUrl + "/404", true); } } } 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 var settings = Context.GetSiteSettings(); var filter = settings.GetValue("VisitorFilter", Constants.DefaultVisitorFilter); 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; var correlate = bool.Parse(settings.GetValue("VisitorCorrelation", "true")); 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 void CreateJwtToken(Alias alias) { var sitesettings = Context.GetSiteSettings(); var secret = sitesettings.GetValue("JwtOptions:Secret", ""); if (!string.IsNullOrEmpty(secret)) { _authorizationToken = JwtManager.GenerateToken(alias, (ClaimsIdentity)Context.User.Identity, secret, sitesettings.GetValue("JwtOptions:Issuer", ""), sitesettings.GetValue("JwtOptions:Audience", ""), int.Parse(sitesettings.GetValue("JwtOptions:Lifetime", "20"))); } } private string CreatePWAScript(Alias alias, Site site, Route route) { return "" + Environment.NewLine + ""; } private string CreateReconnectScript() { return ""; } private string ParseScripts(string content) { // iterate scripts var scripts = ""; if (!string.IsNullOrEmpty(content)) { var index = content.IndexOf("= 0) { scripts += content.Substring(index, content.IndexOf("", index) + 9 - index); index = content.IndexOf(""; } else { // inline script return ""; } } private void SetLocalizationCookie(string culture) { Context.Response.Cookies.Append( CookieRequestCultureProvider.DefaultCookieName, CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture))); } private void ManageStyleSheets(List resources, Alias alias, string name) { if (resources != null) { string batch = DateTime.UtcNow.ToString("yyyyMMddHHmmssfff"); int count = 0; foreach (var resource in resources.Where(item => item.ResourceType == ResourceType.Stylesheet)) { if (resource.Url.StartsWith("~")) { resource.Url = resource.Url.Replace("~", "/Themes/" + Utilities.GetTypeName(name) + "/").Replace("//", "/"); } if (!resource.Url.Contains("://") && alias.BaseUrl != "" && !resource.Url.StartsWith(alias.BaseUrl)) { resource.Url = alias.BaseUrl + resource.Url; } if (!_styleSheets.Contains(resource.Url, StringComparison.OrdinalIgnoreCase)) { count++; string id = "id=\"app-stylesheet-" + ResourceLevel.Page.ToString().ToLower() + "-" + batch + "-" + count.ToString("00") + "\" "; _styleSheets += "" + Environment.NewLine; } } } } private void ManageScripts(List resources, Alias alias) { if (resources != null) { foreach (var resource in resources.Where(item => item.ResourceType == ResourceType.Script)) { AddScript(resource, alias); } } } }