private async Task <IEnumerable <Site> > GetSitesFromCacheAsync() { IEnumerable <Site> sites; var cachedSites = await _cache.GetStringFromCache(CacheKey.Sites); if (cachedSites == null) { sites = await _siteRepository.GetAllAsync(); if (!sites.Any()) { _logger.LogInformation("No sites in database, inserting initial site"); sites = await InsertInitialSiteAsync(); } await _cache.SaveToCacheAsync(CacheKey.Sites, JsonConvert.SerializeObject(sites), 8); _logger.LogTrace("Cache miss on sites: {Count} loaded", sites.Count()); } else { sites = JsonConvert.DeserializeObject <IEnumerable <Site> >(cachedSites); } foreach (var site in sites) { string key = $"s{site.Id}.{CacheKey.SiteSettings}"; var cachedSiteSettings = await _cache.GetStringFromCache(key); if (cachedSiteSettings == null) { site.Settings = await _siteSettingRepository.GetBySiteIdAsync(site.Id); await _cache.SaveToCacheAsync(key, JsonConvert.SerializeObject(site.Settings), 8); _logger.LogTrace("Cache miss on site settings for site id {Id}, {Count} loaded", site.Id, site.Settings.Count); } else { site.Settings = JsonConvert.DeserializeObject <ICollection <SiteSetting> >(cachedSiteSettings); } } return(sites); }
public async Task <StatusSummary> GetCurrentStatsAsync(ReportCriterion request) { if (request.SiteId == null || request.SiteId != GetCurrentSiteId()) { request.SiteId = GetCurrentSiteId(); } string cacheKey = $"s{request.SiteId}.p{request.ProgramId}.sys{request.SystemId}.b{request.BranchId}.{CacheKey.CurrentStats}"; var summaryJson = await _cache.GetStringFromCache(cacheKey); if (string.IsNullOrEmpty(summaryJson)) { var summary = new StatusSummary { RegisteredUsers = await _userRepository.GetCountAsync(request), Achievers = await _userRepository.GetAchieverCountAsync(request), PointsEarned = await _userLogRepository.PointsEarnedTotalAsync(request), CompletedChallenges = await _userLogRepository .CompletedChallengeCountAsync(request), BadgesEarned = await _userLogRepository.EarnedBadgeCountAsync(request), DaysUntilEnd = await GetDaysUntilEnd(), AsOf = _dateTimeProvider.Now }; await _cache.SaveToCacheAsync(cacheKey, JsonConvert.SerializeObject(summary), ExpireInTimeSpan()); return(summary); } else { return(JsonConvert.DeserializeObject <StatusSummary>(summaryJson)); } }
GetGeocodedAddressAsync(string address) { var serviceResult = new ServiceResult <string>(); var(geocodingEnabled, APIKey) = await _siteLookupService.GetSiteSettingStringAsync( GetCurrentSiteId(), SiteSettingKey.Events.GoogleMapsAPIKey); if (!geocodingEnabled) { _logger.LogCritical("Geocoding called without geocoding enabled"); serviceResult.Message = "Geocoding is not enabled."; serviceResult.Status = ServiceResultStatus.Error; return(serviceResult); } var formattedAddress = address.Trim(); var cacheKey = $"a{formattedAddress}.{CacheKey.AddressGeocoding}"; var geolocation = await _cache.GetStringFromCache(cacheKey); if (!string.IsNullOrWhiteSpace(geolocation)) { serviceResult.Status = ServiceResultStatus.Success; serviceResult.Data = geolocation; } else { dynamic jsonResult; using (var client = new HttpClient()) { try { var encodedAddress = WebUtility.UrlEncode(formattedAddress); var response = await client.GetAsync($"https://maps.googleapis.com/maps/api/geocode/json?address={encodedAddress}&key={APIKey}"); response.EnsureSuccessStatusCode(); var stringResult = await response.Content.ReadAsStringAsync(); jsonResult = JsonConvert.DeserializeObject(stringResult); if (jsonResult.status == "ZERO_RESULTS") { serviceResult.Status = ServiceResultStatus.Warning; serviceResult.Message = "No results found for address."; } else if (jsonResult.status != "OK") { _logger.LogError($"Error getting geocoding results for address {address}: {jsonResult.status}"); serviceResult.Status = ServiceResultStatus.Error; serviceResult.Message = "An error occured, please try again later."; } else { var result = jsonResult.results[0]; double latitude = result.geometry.location.lat; double longitude = result.geometry.location.lng; geolocation = $"{latitude},{longitude}"; await _cache.SaveToCacheAsync(cacheKey, geolocation, ExpireInTimeSpan(60)); serviceResult.Status = ServiceResultStatus.Success; serviceResult.Data = geolocation; } } catch (HttpRequestException ex) { _logger.LogCritical(ex, $"Google API error: {ex.Message}"); serviceResult.Status = ServiceResultStatus.Error; serviceResult.Message = "An error occured, please try again later."; } catch (Exception ex) { _logger.LogCritical(ex, ex.Message); serviceResult.Status = ServiceResultStatus.Error; serviceResult.Message = "An error occured, please try again later."; } } } return(serviceResult); }
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next) { Site site = null; await context.HttpContext.Session.LoadAsync(); // if we've already fetched it on this request it's present in Items int?siteId = null; if (context.HttpContext.User.Identity.IsAuthenticated) { // if the user is authenticated, that is their site try { siteId = _userContextProvider.GetId(context.HttpContext.User, ClaimType.SiteId); } catch (Exception ex) { _logger.LogError("Unable to get SiteId claim for user {Name}: {Message}", context.HttpContext.User.Identity.Name, ex.Message); } } if (siteId == null) { string sitePath = context.RouteData.Values["sitePath"]?.ToString(); // first check, did they use a sitePath giving them a specific site if (!string.IsNullOrEmpty(sitePath)) { site = await _siteLookupService.GetSiteByPathAsync(sitePath); if (site != null) { siteId = site.Id; } } // if not check if they already have one in their session if (siteId == null) { siteId = context.HttpContext.Session.GetInt32(SessionKey.SiteId); } // if not then resort to the default if (siteId == null) { siteId = await _siteLookupService.GetDefaultSiteIdAsync(); } } if (site == null) { site = await _siteLookupService.GetByIdAsync((int)siteId); } var siteStage = _siteLookupService.GetSiteStage(site); // we might need to hide challenges and/or events based on system settings // the setting is to hide so the logic is == null rather than != null bool showChallenges = true; bool showEvents = true; if (siteStage == SiteStage.RegistrationOpen || siteStage == SiteStage.BeforeRegistration) { showEvents = site.Settings .FirstOrDefault(_ => _.Key == SiteSettingKey .Events .HideUntilProgramOpen)? .Value == null; } if (siteStage == SiteStage.BeforeRegistration) { showChallenges = site.Settings .FirstOrDefault(_ => _.Key == SiteSettingKey .Challenges .HideUntilRegistrationOpen)? .Value == null; if (!showEvents) { // they might be hidden above showEvents = site.Settings .FirstOrDefault(_ => _.Key == SiteSettingKey .Events .HideUntilRegistrationOpen)? .Value == null; } } context.HttpContext.Items[ItemKey.GoogleAnalytics] = site.GoogleAnalyticsTrackingId; context.HttpContext.Items[ItemKey.RouteId] = context.RouteData.Values["id"]; context.HttpContext.Items[ItemKey.SiteName] = site?.Name ?? _config[ConfigurationKey.DefaultSiteName]; context.HttpContext.Items[ItemKey.SiteStage] = siteStage; context.HttpContext.Session.SetInt32(SessionKey.SiteId, (int)siteId); context.HttpContext.Items[ItemKey.SiteId] = (int)siteId; context.HttpContext.Items[ItemKey.ShowChallenges] = showChallenges; context.HttpContext.Items[ItemKey.ShowEvents] = showEvents; context.HttpContext.Items[ItemKey.WebScheme] = site.IsHttpsForced ? "https" : "http"; // only check if the site.css and site.js have changed periodically by default and // cache the last modification time string siteCssCacheKey = $"s{siteId}.{CacheKey.SiteCss}"; string siteJsCacheKey = $"s{siteId}.{CacheKey.SiteJs}"; var cssLastModified = await _cache.GetStringFromCache(siteCssCacheKey); var jsLastModified = await _cache.GetStringFromCache(siteJsCacheKey); // compute the appropriate cache time in minutes, default to 60 if not provided int cacheMinutes = 60; var cacheSiteCustomizationsMinutes = site.Settings .FirstOrDefault(_ => _.Key == SiteSettingKey.Web.CacheSiteCustomizationsMinutes)? .Value; if (cacheSiteCustomizationsMinutes != null && !int.TryParse(cacheSiteCustomizationsMinutes, out cacheMinutes)) { _logger.LogError("Could not convert cache site customizations value to a number: {cacheSiteCustomizationsMinutes}", cacheSiteCustomizationsMinutes); } // kill any cached values if the cache value was set to 0 if (cacheMinutes == 0) { if (!string.IsNullOrEmpty(cssLastModified)) { await _cache.RemoveAsync(siteCssCacheKey); } if (!string.IsNullOrEmpty(jsLastModified)) { await _cache.RemoveAsync(siteJsCacheKey); } } // check for a cache miss and compute the appropriate last modification date if (string.IsNullOrEmpty(cssLastModified) || string.IsNullOrEmpty(jsLastModified)) { // file path to the site.css file string file = _pathResolver.ResolveContentFilePath( Path.Combine($"site{siteId}", "styles", "site.css")); cssLastModified = await UpdateCacheAsync(file, cacheMinutes, cssLastModified, siteCssCacheKey); // file path to the site.js file file = _pathResolver.ResolveContentFilePath( Path.Combine($"site{siteId}", "scripts", "site.js")); jsLastModified = await UpdateCacheAsync(file, cacheMinutes, jsLastModified, siteJsCacheKey); } // if we have values then set appropriate HttpContext.Items if (!string.IsNullOrEmpty(cssLastModified) || !string.IsNullOrEmpty(jsLastModified)) { string contentPath = _config[ConfigurationKey.ContentPath].StartsWith("/") ? _config[ConfigurationKey.ContentPath] : $"/{_config[ConfigurationKey.ContentPath]}"; if (!string.IsNullOrEmpty(cssLastModified)) { context.HttpContext.Items[ItemKey.SiteCss] = $"{contentPath}/site{siteId}/styles/site.css?v={cssLastModified}"; } if (!string.IsNullOrEmpty(jsLastModified)) { context.HttpContext.Items[ItemKey.SiteJs] = $"{contentPath}/site{siteId}/scripts/site.js?v={jsLastModified}"; } } context.HttpContext.Items[ItemKey.HouseholdTitle] = string.IsNullOrEmpty(context .HttpContext .Session .GetString(SessionKey.CallItGroup)) ? Annotations.Interface.Family : Annotations.Interface.Group; if (!string.IsNullOrWhiteSpace(site.ExternalEventListUrl)) { context.HttpContext.Items[ItemKey.ExternalEventListUrl] = site.ExternalEventListUrl; } var currentCulture = _userContextProvider.GetCurrentCulture(); context.HttpContext.Items[ItemKey.ISOLanguageName] = currentCulture.TwoLetterISOLanguageName; int?activeUserId = _userContextProvider.GetContext().ActiveUserId; if (_l10nOptions.Value?.SupportedCultures.Count > 1) { var cookieCulture = context .HttpContext .Request .Cookies[CookieRequestCultureProvider.DefaultCookieName]; if (currentCulture.Name == Culture.DefaultName) { if (cookieCulture != null) { context .HttpContext .Response .Cookies .Delete(CookieRequestCultureProvider.DefaultCookieName); if (activeUserId != null) { await _userService.UpdateCulture(null); } } } else { // no cookie or new culture selected, reset cookie context.HttpContext.Response.Cookies.Append( CookieRequestCultureProvider.DefaultCookieName, CookieRequestCultureProvider .MakeCookieValue(new RequestCulture(currentCulture.Name)), new CookieOptions { Expires = DateTimeOffset.UtcNow.AddDays(14) } ); if (activeUserId != null) { await _userService.UpdateCulture(currentCulture.Name); } } // generate list for drop-down var cultureList = new List <SelectListItem>(); var cultureHrefLang = new Dictionary <string, string> { { "x-default", Culture.DefaultName } }; foreach (var culture in _l10nOptions.Value.SupportedCultures) { var text = culture.Parent != null ? culture.Parent.NativeName : culture.NativeName; cultureList.Add(new SelectListItem(text, culture.Name)); if (!cultureHrefLang.Keys.Contains(culture.Name)) { cultureHrefLang.Add(culture.Name, culture.Name); if (culture.Parent != null && !cultureHrefLang.Keys.Contains(culture.Parent.Name)) { cultureHrefLang.Add(culture.Parent.Name, culture.Parent.Name); } } } context.HttpContext.Items[ItemKey.HrefLang] = cultureHrefLang; context.HttpContext.Items[ItemKey.L10n] = cultureList.OrderBy(_ => _.Text); } using (LogContext.PushProperty(LoggingEnrichment.ActiveUserId, activeUserId)) using (LogContext.PushProperty(LoggingEnrichment.LanguageId, currentCulture?.TwoLetterISOLanguageName)) using (LogContext.PushProperty(LoggingEnrichment.RouteAction, context.RouteData?.Values["action"])) using (LogContext.PushProperty(LoggingEnrichment.RouteArea, context.RouteData?.Values["area"])) using (LogContext.PushProperty(LoggingEnrichment.RouteController, context.RouteData?.Values["controller"])) using (LogContext.PushProperty(LoggingEnrichment.RouteId, context.RouteData?.Values["id"])) using (LogContext.PushProperty(LoggingEnrichment.SiteStage, siteStage)) { await next(); } }
public async Task <Social> GetAsync(string culture) { var expiration = DateTime.Now.AddHours(CacheInHours).Ticks; int?headerId = await _cache.GetIntFromCacheAsync(CacheKey.SocialHeader); if (!headerId.HasValue) { var headerIdRecord = await _socialHeaderRepository .GetByDateAsync(_dateTimeProvider.Now); if (headerIdRecord == null) { return(null); } if (headerIdRecord.NextStartDate.HasValue && headerIdRecord.NextStartDate.Value != default) { expiration = Math.Min(expiration, headerIdRecord.NextStartDate.Value.Ticks); } await _cache.SaveToCacheAsync(CacheKey.SocialHeader, headerIdRecord.Id, TimeSpan.FromTicks(expiration)); headerId = headerIdRecord.Id; } if (!headerId.HasValue) { return(null); } var languageId = await _languageService.GetLanguageIdAsync(culture); Social social = null; var cacheKey = GetCacheKey(CacheKey.Social, headerId.Value, languageId); var socialCache = await _cache.GetStringFromCache(cacheKey); if (!string.IsNullOrEmpty(socialCache)) { try { social = JsonSerializer.Deserialize <Social>(socialCache); } catch (JsonException jex) { _logger.LogError("Unable to deserialize social object: {ErrorMessage}", jex.Message); } } if (social == null) { social = await _socialRepository.GetByHeaderLanguageAsync(headerId.Value, languageId); await _cache.SaveToCacheAsync(cacheKey, JsonSerializer.Serialize(social), TimeSpan.FromTicks(expiration)); } return(social); }