/// <summary> /// Creates the asset from blob object. /// </summary> /// <param name="assetStorageProvider">The asset storage provider.</param> /// <param name="blobItem">The blob object.</param> /// <param name="createThumbnail">if set to <c>true</c> [create thumbnail].</param> /// <returns></returns> private Asset TranslateBlobToRockAsset(AssetStorageProvider assetStorageProvider, CloudBlob blobItem, bool createThumbnail = true) { var asset = new Asset { Name = GetNameFromKey(blobItem.Name), Key = blobItem.Name, Uri = blobItem.Uri.ToString(), Type = AssetType.File, AssetStorageProviderId = assetStorageProvider.Id }; if (blobItem.Properties != null) { asset.FileSize = blobItem.Properties.Length; asset.Description = $"{blobItem.Properties.Length} byte{( blobItem.Properties.Length == 1 ? string.Empty : "s" )}"; if (blobItem.Properties.LastModified != null) { asset.LastModifiedDateTime = RockDateTime.ConvertLocalDateTimeToRockDateTime(blobItem.Properties.LastModified.Value.LocalDateTime); } } if (createThumbnail) { asset.IconPath = createThumbnail ? GetThumbnail(assetStorageProvider, blobItem.Name, asset.LastModifiedDateTime) : GetFileTypeIcon(blobItem.Name); } return(asset); }
public void TestFirstDateOfWeekTuesday() { var sundayDate20191006 = new DateTime(2019, 10, 6); var sundayDate20191013 = new DateTime(2019, 10, 13); var sundayDate20191020 = new DateTime(2019, 10, 20); var sundayDate20191027 = new DateTime(2019, 10, 27); Rock.Web.SystemSettings.SetValue(Rock.SystemKey.SystemSetting.START_DAY_OF_WEEK, DayOfWeek.Tuesday.ConvertToInt().ToString()); RockDateTime.UpdateSundayDateData(); Assert.That.IsTrue(new DateTime(2019, 10, 1).SundayDate() == sundayDate20191006, "Incorrect Sunday Date"); Assert.That.IsTrue(new DateTime(2019, 10, 5).SundayDate() == sundayDate20191006, "Incorrect Sunday Date"); Assert.That.IsTrue(new DateTime(2019, 10, 6).SundayDate() == sundayDate20191006, "Incorrect Sunday Date"); Assert.That.IsTrue(new DateTime(2019, 10, 7).SundayDate() == sundayDate20191006, "Incorrect Sunday Date"); Assert.That.IsTrue(new DateTime(2019, 10, 8).SundayDate() == sundayDate20191013, "Incorrect Sunday Date"); Assert.That.IsTrue(new DateTime(2019, 10, 14).SundayDate() == sundayDate20191013, "Incorrect Sunday Date"); Assert.That.IsTrue(new DateTime(2019, 10, 13).SundayDate() == sundayDate20191013, "Incorrect Sunday Date"); Assert.That.IsTrue(new DateTime(2019, 10, 21).SundayDate() == sundayDate20191020, "Incorrect Sunday Date"); Assert.That.IsTrue(new DateTime(2019, 10, 22).SundayDate() != sundayDate20191020, "Incorrect Sunday Date"); Assert.That.IsTrue(new DateTime(2019, 10, 22).SundayDate() == sundayDate20191027, "Incorrect Sunday Date"); var rockContext = new RockContext(); Assert.That.IsTrue(rockContext.Database.SqlQuery <DateTime>($@"SELECT dbo.ufnUtility_GetSundayDate('{new DateTime( 2019, 10, 1 )}')").FirstOrDefault() == sundayDate20191006, "Incorrect Sunday Date"); Assert.That.IsTrue(rockContext.Database.SqlQuery <DateTime>($@"SELECT dbo.ufnUtility_GetSundayDate('{new DateTime( 2019, 10, 5 )}')").FirstOrDefault() == sundayDate20191006, "Incorrect Sunday Date"); Assert.That.IsTrue(rockContext.Database.SqlQuery <DateTime>($@"SELECT dbo.ufnUtility_GetSundayDate('{new DateTime( 2019, 10, 6 )}')").FirstOrDefault() == sundayDate20191006, "Incorrect Sunday Date"); Assert.That.IsTrue(rockContext.Database.SqlQuery <DateTime>($@"SELECT dbo.ufnUtility_GetSundayDate('{new DateTime( 2019, 10, 7 )}')").FirstOrDefault() == sundayDate20191006, "Incorrect Sunday Date"); Assert.That.IsTrue(rockContext.Database.SqlQuery <DateTime>($@"SELECT dbo.ufnUtility_GetSundayDate('{new DateTime( 2019, 10, 8 )}')").FirstOrDefault() == sundayDate20191013, "Incorrect Sunday Date"); Assert.That.IsTrue(rockContext.Database.SqlQuery <DateTime>($@"SELECT dbo.ufnUtility_GetSundayDate('{new DateTime( 2019, 10, 14 )}')").FirstOrDefault() == sundayDate20191013, "Incorrect Sunday Date"); Assert.That.IsTrue(rockContext.Database.SqlQuery <DateTime>($@"SELECT dbo.ufnUtility_GetSundayDate('{new DateTime( 2019, 10, 13 )}')").FirstOrDefault() == sundayDate20191013, "Incorrect Sunday Date"); Assert.That.IsTrue(rockContext.Database.SqlQuery <DateTime>($@"SELECT dbo.ufnUtility_GetSundayDate('{new DateTime( 2019, 10, 21 )}')").FirstOrDefault() == sundayDate20191020, "Incorrect Sunday Date"); Assert.That.IsTrue(rockContext.Database.SqlQuery <DateTime>($@"SELECT dbo.ufnUtility_GetSundayDate('{new DateTime( 2019, 10, 22 )}')").FirstOrDefault() != sundayDate20191020, "Incorrect Sunday Date"); Assert.That.IsTrue(rockContext.Database.SqlQuery <DateTime>($@"SELECT dbo.ufnUtility_GetSundayDate('{new DateTime( 2019, 10, 22 )}')").FirstOrDefault() == sundayDate20191027, "Incorrect Sunday Date"); }
private void LoadFiscalYearList() { ddlFiscalYear.Items.Insert(0, new ListItem("All", DateTime.MinValue.ToString())); for (int i = 0; i <= 10; i++) { string date = RockDateTime.New(RockDateTime.Now.Year - i, 1, 1).ToString(); ddlFiscalYear.Items.Insert(0, new ListItem((RockDateTime.Now.Year - i).ToString(), date.ToString())); } }
/// <summary> /// Sets the RockDateTime timezone to a value that is suitable for testing an operating environment /// in which the organization timezone does not match the local system timezone. /// This configuration simulates a Rock server hosted in a different timezone to the Rock organization. /// </summary> public static void SetRockDateTimeToAlternateTimezone() { var tz = GetTestTimeZoneAlternate(); RockDateTime.Initialize(tz); // Re-initialize the lava engine options. var options = GetCurrentEngineOptions(); _fluidEngine.Initialize(options); }
/// <summary> /// Returns a human-friendly description of the time of day. /// </summary> /// <param name="input">A valid date/time value</param> /// <returns></returns> public static string TimeOfDay(object input) { var dtoInput = GetDateTimeOffsetFromInputParameter(input, null); if (dtoInput == null) { return(string.Empty); } var response = RockDateTime.GetTimeOfDay(dtoInput.Value.DateTime); return(response); }
public void TestFirstDateOfWeekMonday() { var sundayDate20190825 = new DateTime(2019, 8, 25); var sundayDate20190901 = new DateTime(2019, 9, 1); var sundayDate20190908 = new DateTime(2019, 9, 8); var sundayDate20190915 = new DateTime(2019, 9, 15); var sundayDate20190922 = new DateTime(2019, 9, 22); Rock.Web.SystemSettings.SetValue(Rock.SystemKey.SystemSetting.START_DAY_OF_WEEK, DayOfWeek.Monday.ConvertToInt().ToString()); RockDateTime.UpdateSundayDateData(); Assert.That.IsTrue(new DateTime(2019, 8, 23).SundayDate() == sundayDate20190825, "Incorrect Sunday Date"); Assert.That.IsTrue(new DateTime(2019, 8, 24).SundayDate() == sundayDate20190825, "Incorrect Sunday Date"); Assert.That.IsTrue(new DateTime(2019, 8, 25).SundayDate() == sundayDate20190825, "Incorrect Sunday Date"); Assert.That.IsTrue(new DateTime(2019, 8, 26).SundayDate() == sundayDate20190901, "Incorrect Sunday Date"); Assert.That.IsTrue(new DateTime(2019, 8, 27).SundayDate() == sundayDate20190901, "Incorrect Sunday Date"); Assert.That.IsTrue(new DateTime(2019, 8, 28).SundayDate() == sundayDate20190901, "Incorrect Sunday Date"); Assert.That.IsTrue(new DateTime(2019, 8, 29).SundayDate() == sundayDate20190901, "Incorrect Sunday Date"); Assert.That.IsTrue(new DateTime(2019, 8, 30).SundayDate() == sundayDate20190901, "Incorrect Sunday Date"); Assert.That.IsTrue(new DateTime(2019, 9, 5).SundayDate() == sundayDate20190908, "Incorrect Sunday Date"); Assert.That.IsTrue(new DateTime(2019, 9, 9).SundayDate() == sundayDate20190915, "Incorrect Sunday Date"); Assert.That.IsTrue(new DateTime(2019, 9, 17).SundayDate() == sundayDate20190922, "Incorrect Sunday Date"); var attendanceOccurrence = new AttendanceOccurrence() { OccurrenceDate = new DateTime(2019, 9, 17) }; Assert.That.IsTrue(attendanceOccurrence.SundayDate == new DateTime(2019, 9, 17).SundayDate()); attendanceOccurrence = new AttendanceOccurrence() { OccurrenceDate = new DateTime(2019, 9, 19) }; Assert.That.IsTrue(attendanceOccurrence.SundayDate == new DateTime(2019, 9, 19).SundayDate()); var rockContext = new RockContext(); Assert.That.IsTrue(rockContext.Database.SqlQuery <DateTime>($@"SELECT dbo.ufnUtility_GetSundayDate('{new DateTime( 2019, 8, 23 )}')").FirstOrDefault() == sundayDate20190825, "Incorrect Sunday Date (SQL)"); Assert.That.IsTrue(rockContext.Database.SqlQuery <DateTime>($@"SELECT dbo.ufnUtility_GetSundayDate('{new DateTime( 2019, 8, 24 )}')").FirstOrDefault() == sundayDate20190825, "Incorrect Sunday Date (SQL)"); Assert.That.IsTrue(rockContext.Database.SqlQuery <DateTime>($@"SELECT dbo.ufnUtility_GetSundayDate('{new DateTime( 2019, 8, 25 )}')").FirstOrDefault() == sundayDate20190825, "Incorrect Sunday Date (SQL)"); Assert.That.IsTrue(rockContext.Database.SqlQuery <DateTime>($@"SELECT dbo.ufnUtility_GetSundayDate('{new DateTime( 2019, 8, 26 )}')").FirstOrDefault() == sundayDate20190901, "Incorrect Sunday Date (SQL)"); Assert.That.IsTrue(rockContext.Database.SqlQuery <DateTime>($@"SELECT dbo.ufnUtility_GetSundayDate('{new DateTime( 2019, 8, 27 )}')").FirstOrDefault() == sundayDate20190901, "Incorrect Sunday Date (SQL)"); Assert.That.IsTrue(rockContext.Database.SqlQuery <DateTime>($@"SELECT dbo.ufnUtility_GetSundayDate('{new DateTime( 2019, 8, 28 )}')").FirstOrDefault() == sundayDate20190901, "Incorrect Sunday Date (SQL)"); Assert.That.IsTrue(rockContext.Database.SqlQuery <DateTime>($@"SELECT dbo.ufnUtility_GetSundayDate('{new DateTime( 2019, 8, 29 )}')").FirstOrDefault() == sundayDate20190901, "Incorrect Sunday Date (SQL)"); Assert.That.IsTrue(rockContext.Database.SqlQuery <DateTime>($@"SELECT dbo.ufnUtility_GetSundayDate('{new DateTime( 2019, 8, 30 )}')").FirstOrDefault() == sundayDate20190901, "Incorrect Sunday Date (SQL)"); Assert.That.IsTrue(rockContext.Database.SqlQuery <DateTime>($@"SELECT dbo.ufnUtility_GetSundayDate('{new DateTime( 2019, 9, 5 )}')").FirstOrDefault() == sundayDate20190908, "Incorrect Sunday Date (SQL)"); Assert.That.IsTrue(rockContext.Database.SqlQuery <DateTime>($@"SELECT dbo.ufnUtility_GetSundayDate('{new DateTime( 2019, 9, 9 )}')").FirstOrDefault() == sundayDate20190915, "Incorrect Sunday Date (SQL)"); Assert.That.IsTrue(rockContext.Database.SqlQuery <DateTime>($@"SELECT dbo.ufnUtility_GetSundayDate('{new DateTime( 2019, 9, 17 )}')").FirstOrDefault() == sundayDate20190922, "Incorrect Sunday Date (SQL)"); }
/// <inheritdoc/> public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Date && reader.Value is DateTimeOffset dateTimeOffset) { return(RockDateTime.ConvertLocalDateTimeToRockDateTime(dateTimeOffset.LocalDateTime)); } else if (reader.TokenType == JsonToken.Date && reader.Value is DateTime dateTime) { return(RockDateTime.ConvertLocalDateTimeToRockDateTime(dateTime)); } else { return(null); } }
/// <inheritdoc/> public override object ConvertTo(Type type, CultureInfo culture) { if (type == typeof(DateTime) || type == typeof(DateTime? )) { var value = base.ConvertTo(type, culture); // If the value is a DateTime then it will be in the local system // date and time. Convert it to Rock Organization date time. if (value is DateTime dateTime) { return(RockDateTime.ConvertLocalDateTimeToRockDateTime(dateTime)); } } return(base.ConvertTo(type, culture)); }
/// <summary> /// Sets the RockDateTime timezone to a value that is suitable for testing an operating environment /// in which the organization timezone supports daylight saving time. /// </summary> public static void SetRockDateTimeToDaylightSavingTimezone() { // Set to Mountain Standard Time (MST), a timezone that supports Daylight Saving Time (DST). var tz = TimeZoneInfo.FindSystemTimeZoneById("US Mountain Standard Time"); Assert.That.IsNotNull(tz, "Timezone 'MST' is not available in this environment."); Assert.That.IsTrue(tz.SupportsDaylightSavingTime, "Test Timezone should be configured for Daylight Saving Time (DST)."); RockDateTime.Initialize(tz); // Re-initialize the lava engine options. var options = GetCurrentEngineOptions(); _fluidEngine.Initialize(options); }
/// <summary> /// Sets the RockDateTime timezone to a value that is suitable for testing an operating environment /// in which the organization timezone does not match the local system timezone. /// This configuration simulates a Rock server hosted in a different timezone to the Rock organization. /// </summary> public static void SetRockOrganizationTimeZone(string timeZoneId) { try { var tz = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId); RockDateTime.Initialize(tz); } catch (TimeZoneNotFoundException) { throw new Exception($"Timezone '{timeZoneId}' is not available in this environment."); } // Re-initialize the lava engine options. var options = GetCurrentEngineOptions(); _fluidEngine.Initialize(options); }
/// <summary> /// Cleans expired cached files from the cache folder /// </summary> /// <param name="directoryPath">The directory path.</param> /// <param name="expirationDate">The file expiration date. Files older than this date will be deleted</param> private void CleanCacheDirectory(string directoryPath, DateTime expirationDate) { // verify that the directory exists if (!Directory.Exists(directoryPath)) { // if directory doesn't exist return return; } // loop through each file in the directory foreach (string filePath in Directory.GetFiles(directoryPath)) { // if the file creation date is older than the expiration date DateTime adjustedFileDateTime = RockDateTime.ConvertLocalDateTimeToRockDateTime(File.GetCreationTime(filePath)); if (adjustedFileDateTime < expirationDate) { // delete the file DeleteFile(filePath, false); } } // loop through each subdirectory in the current directory foreach (string subDirectory in Directory.GetDirectories(directoryPath)) { // if the directory is not a reparse point if ((File.GetAttributes(subDirectory) & FileAttributes.ReparsePoint) != FileAttributes.ReparsePoint) { // clean the directory CleanCacheDirectory(subDirectory, expirationDate); } } // get subdirectory and file count int directoryCount = Directory.GetDirectories(directoryPath).Length; int fileCount = Directory.GetFiles(directoryPath).Length; // if directory is empty if ((directoryCount + fileCount) == 0) { // delete the directory DeleteDirectory(directoryPath, false); } }
private void ProcessForWorkflow(Guid?actionGuid, Rock.Data.RockContext rockContext, SendGridEvent payload) { RockLogger.Log.Debug(RockLogDomains.Communications, "ProcessForWorkflow {@payload}", payload); string status = string.Empty; switch (payload.EventType) { case "unsubscribe": case "delivered": status = SendEmailWithEvents.SENT_STATUS; break; case "click": status = SendEmailWithEvents.CLICKED_STATUS; break; case "open": status = SendEmailWithEvents.OPENED_STATUS; break; case "failed": case "dropped": case "blocked": case "bounce": case "bounced": status = SendEmailWithEvents.FAILED_STATUS; string message = payload.ServerResponse.IsNotNullOrWhiteSpace() ? payload.ServerResponse : payload.EventTypeReason; Rock.Communication.Email.ProcessBounce( payload.Email, Rock.Communication.BounceType.HardBounce, message, RockDateTime.ConvertLocalDateTimeToRockDateTime(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(payload.Timestamp).ToLocalTime())); break; } if (actionGuid != null && !string.IsNullOrWhiteSpace(status)) { SendEmailWithEvents.UpdateEmailStatus(actionGuid.Value, status, payload.EventType, rockContext, true); } }
/// <summary> /// Checks if the interaction is for a communication and if so do /// additional steps to mark the communication as opened.. /// </summary> /// <param name="session">The interaction session.</param> /// <param name="interaction">The interaction data.</param> /// <param name="rockContext">The rock context.</param> private void ProcessCommunicationInteraction(MobileInteractionSession session, MobileInteraction interaction, Rock.Data.RockContext rockContext) { // The interaction must be for the communication channel. if (interaction.ChannelGuid != _communicationInteractionChannelGuid && interaction.ChannelId != CommunicationInteractionChannelId) { return; } // We need the communication recipient identifier and the communication identifier. if (!interaction.EntityId.HasValue || !interaction.ComponentEntityId.HasValue) { return; } // Only process "Opened" operations for now. if (!interaction.Operation.Equals("OPENED", StringComparison.OrdinalIgnoreCase)) { return; } // Because this is a mostly open API, don't trust just the // recipient identifier. Do a query that makes sure both the // communication identifier and the recipient identifier match // for a bit of extra security. var communicationRecipient = new CommunicationRecipientService(rockContext).Queryable() .Where(a => a.Id == interaction.EntityId && a.CommunicationId == interaction.ComponentEntityId) .FirstOrDefault(); if (communicationRecipient == null) { return; } communicationRecipient.Status = CommunicationRecipientStatus.Opened; communicationRecipient.OpenedDateTime = RockDateTime.ConvertLocalDateTimeToRockDateTime(interaction.DateTime.LocalDateTime); communicationRecipient.OpenedClient = string.Format( "{0} {1} ({2})", session.OperatingSystem ?? "unknown", session.Application ?? "unknown", session.ClientType ?? "unknown"); }
/// <summary> /// Initializes the Rock organization time zone. /// </summary> private static void InitializeRockOrgTimeZone() { string orgTimeZoneSetting = ConfigurationManager.AppSettings["OrgTimeZone"]; if (string.IsNullOrWhiteSpace(orgTimeZoneSetting)) { RockDateTime.Initialize(TimeZoneInfo.Local); } else { // if Web.Config has the OrgTimeZone set to the special "Local" (intended for Developer Mode), just use the Local DateTime. However, a production install of Rock will always have a real Time Zone string if (orgTimeZoneSetting.Equals("Local", StringComparison.OrdinalIgnoreCase)) { RockDateTime.Initialize(TimeZoneInfo.Local); } else { RockDateTime.Initialize(TimeZoneInfo.FindSystemTimeZoneById(orgTimeZoneSetting)); } } }
/// <summary> /// Processes for workflow. /// </summary> /// <param name="eventType">Type of the event.</param> /// <param name="actionGuid">The action unique identifier.</param> /// <param name="rockContext">The rock context.</param> private void ProcessForWorkflow(Guid?actionGuid, Rock.Data.RockContext rockContext) { string status = string.Empty; switch (mailgunRequestPayload.EventType) { case "complained": case "unsubscribed": case "delivered": status = SendEmailWithEvents.SENT_STATUS; break; case "clicked": status = SendEmailWithEvents.CLICKED_STATUS; break; case "opened": status = SendEmailWithEvents.OPENED_STATUS; break; case "failed": case "dropped": case "suppress-bounce": case "bounced": status = SendEmailWithEvents.FAILED_STATUS; string message = mailgunRequestPayload.Notification.IsNotNullOrWhiteSpace() ? mailgunRequestPayload.Notification : mailgunRequestPayload.Description; Rock.Communication.Email.ProcessBounce( mailgunRequestPayload.Recipient, Rock.Communication.BounceType.HardBounce, message, RockDateTime.ConvertLocalDateTimeToRockDateTime(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(mailgunRequestPayload.TimeStamp).ToLocalTime())); break; } if (actionGuid != null && !string.IsNullOrWhiteSpace(status)) { SendEmailWithEvents.UpdateEmailStatus(actionGuid.Value, status, mailgunRequestPayload.EventType, rockContext, true); } }
/// <summary> /// Handles the Click event of the btnSaveStartDayOfWeek control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> protected void btnSaveStartDayOfWeek_Click(object sender, EventArgs e) { if (dowpStartingDayOfWeek.SelectedDayOfWeek != RockDateTime.FirstDayOfWeek) { Rock.Web.SystemSettings.SetValue(Rock.SystemKey.SystemSetting.START_DAY_OF_WEEK, dowpStartingDayOfWeek.SelectedDayOfWeek.ConvertToInt().ToString()); Task.Run(() => { try { RockDateTime.UpdateSundayDateData(); } catch (Exception ex) { ExceptionLogService.LogException(new Exception("An error occurred applying the Start Of Week setting", ex)); } }); nbStartDayOfWeekSaveMessage.NotificationBoxType = NotificationBoxType.Success; nbStartDayOfWeekSaveMessage.Title = string.Empty; nbStartDayOfWeekSaveMessage.Text = string.Format("Start Day of Week is now set to <strong>{0}</strong>. ", dowpStartingDayOfWeek.SelectedDayOfWeek.ConvertToString()); } }
/// <summary> /// Processes for workflow. /// </summary> /// <param name="eventType">Type of the event.</param> /// <param name="actionGuid">The action unique identifier.</param> /// <param name="rockContext">The rock context.</param> private void ProcessForWorkflow(string eventType, Guid?actionGuid, Rock.Data.RockContext rockContext) { string status = string.Empty; switch (eventType) { case "complained": case "unsubscribed": case "delivered": status = SendEmailWithEvents.SENT_STATUS; break; case "clicked": status = SendEmailWithEvents.CLICKED_STATUS; break; case "opened": status = SendEmailWithEvents.OPENED_STATUS; break; case "dropped": case "suppress-bounce": case "bounced": status = SendEmailWithEvents.FAILED_STATUS; int secs = request.Form["timestamp"].AsInteger(); Rock.Communication.Email.ProcessBounce( request.Form["recipient"], Rock.Communication.BounceType.HardBounce, request.Form["notification"], RockDateTime.ConvertLocalDateTimeToRockDateTime(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(secs).ToLocalTime())); break; } if (actionGuid != null && !string.IsNullOrWhiteSpace(status)) { SendEmailWithEvents.UpdateEmailStatus(actionGuid.Value, status, eventType, rockContext, true); } }
/// <summary> /// Processes the binary file request. /// </summary> /// <param name="context">The context.</param> private void ProcessBinaryFileRequest(HttpContext context) { int fileId = context.Request.QueryString["id"].AsInteger(); Guid fileGuid = context.Request.QueryString["guid"].AsGuid(); if (fileId == 0 && fileGuid == Guid.Empty) { SendBadRequest(context, "File id key must be a guid or an int."); return; } var rockContext = new RockContext(); var binaryFileQuery = new BinaryFileService(rockContext).Queryable(); if (fileGuid != Guid.Empty) { binaryFileQuery = binaryFileQuery.Where(a => a.Guid == fileGuid); } else { binaryFileQuery = binaryFileQuery.Where(a => a.Id == fileId); } //// get just the binaryFileMetaData (not the file content) just in case we can get the filecontent faster from the cache //// a null ModifiedDateTime shouldn't happen, but just in case, set it to DateTime.MaxValue so we error on the side of not getting it from the cache var binaryFileMetaData = binaryFileQuery.Select(a => new { a.Id, BinaryFileType_AllowCaching = a.BinaryFileType.AllowCaching, BinaryFileType_RequiresViewSecurity = a.BinaryFileType.RequiresViewSecurity, ModifiedDateTime = a.ModifiedDateTime ?? DateTime.MaxValue, a.MimeType, a.FileName }).FirstOrDefault(); if (binaryFileMetaData == null) { SendNotFound(context); return; } //// if the binaryFile's BinaryFileType requires view security, check security //// note: we put a RequiresViewSecurity flag on BinaryFileType because checking security for every image would be slow (~40ms+ per image request) if (binaryFileMetaData.BinaryFileType_RequiresViewSecurity) { var currentUser = new UserLoginService(rockContext).GetByUserName(UserLogin.GetCurrentUserName()); Person currentPerson = currentUser != null ? currentUser.Person : null; BinaryFile binaryFileAuth = new BinaryFileService(rockContext).Queryable("BinaryFileType").First(a => a.Id == binaryFileMetaData.Id); if (!binaryFileAuth.IsAuthorized(Authorization.VIEW, currentPerson)) { SendNotAuthorized(context); return; } } Stream fileContent = null; try { // Is it cached string cacheName = UrlQueryToCachedFileName(context.Request.QueryString, binaryFileMetaData.MimeType); string physCachedFilePath = context.Request.MapPath(string.Format("~/App_Data/Cache/{0}", cacheName)); if (binaryFileMetaData.BinaryFileType_AllowCaching && File.Exists(physCachedFilePath)) { //// Compare the File's LastWrite DateTime (which comes from the OS's clock), adjust it for the Rock OrgTimeZone, then compare to BinaryFile's ModifiedDateTime (which is already in OrgTimeZone). //// If the BinaryFile record in the database is less recent than the last time this was cached, it is safe to use the Cached version. //// NOTE: A BinaryFile record is typically just added and never modified (a modify is just creating a new BinaryFile record and deleting the old one), so the cached version will probably always be the correct choice. DateTime cachedFileDateTime = RockDateTime.ConvertLocalDateTimeToRockDateTime(File.GetLastWriteTime(physCachedFilePath)); if (binaryFileMetaData.ModifiedDateTime < cachedFileDateTime) { // NOTE: the cached file has already been resized (the size is part of the cached file's filename), so we don't need to resize it again fileContent = FetchFromCache(physCachedFilePath); } } if (fileContent == null) { // If we didn't get it from the cache, get it from the binaryFileService BinaryFile binaryFile = GetFromBinaryFileService(context, binaryFileMetaData.Id); if (binaryFile != null) { fileContent = binaryFile.ContentStream; } // If we got the image from the binaryFileService, it might need to be resized and cached if (fileContent != null) { // If more than 1 query string param is passed in, or the mime type is TIFF, assume resize is needed // Note: we force "image/tiff" to get resized so that it gets converted into a jpg (browsers don't like tiffs) if (context.Request.QueryString.Count > 1 || binaryFile.MimeType == "image/tiff") { // if it isn't an SVG file, do a Resize if (binaryFile.MimeType != "image/svg+xml") { fileContent = GetResized(context.Request.QueryString, fileContent); } } if (binaryFileMetaData.BinaryFileType_AllowCaching) { Cache(fileContent, physCachedFilePath); // Reset stream if (fileContent.CanSeek) { fileContent.Seek(0, SeekOrigin.Begin); } else { fileContent = FetchFromCache(physCachedFilePath); } } } } if (fileContent == null) { // if we couldn't get the file from the binaryFileServie or the cache, respond with NotFound SendNotFound(context); return; } // respond with File if (binaryFileMetaData.BinaryFileType_AllowCaching) { // if binaryFileType is set to allowcaching, also tell the browser to cache it for 365 days context.Response.Cache.SetLastModified(binaryFileMetaData.ModifiedDateTime); context.Response.Cache.SetMaxAge(new TimeSpan(365, 0, 0, 0)); } // set the mime-type to that of the binary file context.Response.ContentType = binaryFileMetaData.MimeType != "image/tiff" ? binaryFileMetaData.MimeType : "image/jpg"; // check that the format of the image wasn't changed by a format query parm if so adjust the mime-type to reflect the conversion if (context.Request["format"].IsNotNullOrWhitespace()) { switch (context.Request["format"]) { case "png": { context.Response.ContentType = "image/png"; break; } case "gif": { context.Response.ContentType = "image/gif"; break; } case "jpg": { context.Response.ContentType = "image/jpeg"; break; } } } using (var responseStream = fileContent) { context.Response.AddHeader("content-disposition", "inline;filename=" + binaryFileMetaData.FileName.MakeValidFileName().UrlEncode()); if (responseStream.CanSeek) { responseStream.Seek(0, SeekOrigin.Begin); } responseStream.CopyTo(context.Response.OutputStream); context.Response.Flush(); } } finally { if (fileContent != null) { fileContent.Dispose(); } } }
/// <summary> /// Processes the binary file request. /// </summary> /// <param name="context">The context.</param> private void ProcessBinaryFileRequest(HttpContext context) { int fileId = context.Request.QueryString["id"].AsInteger() ?? 0; Guid fileGuid = context.Request.QueryString["guid"].AsGuid(); if (fileId == 0 && fileGuid.Equals(Guid.Empty)) { SendNotFound(context); } var rockContext = new RockContext(); var binaryFileQuery = new BinaryFileService(rockContext).Queryable(); if (fileGuid != Guid.Empty) { binaryFileQuery = binaryFileQuery.Where(a => a.Guid == fileGuid); } else { binaryFileQuery = binaryFileQuery.Where(a => a.Id == fileId); } //// get just the binaryFileMetaData (not the file content) just in case we can get the filecontent faster from the cache //// a null ModifiedDateTime shouldn't happen, but just in case, set it to DateTime.MaxValue so we error on the side of not getting it from the cache var binaryFileMetaData = binaryFileQuery.Select(a => new { BinaryFileType_AllowCaching = a.BinaryFileType.AllowCaching, BinaryFileType_RequiresSecurity = a.BinaryFileType.RequiresSecurity, ModifiedDateTime = a.ModifiedDateTime ?? DateTime.MaxValue, a.MimeType, a.FileName }).FirstOrDefault(); if (binaryFileMetaData == null) { SendNotFound(context); return; } //// if the binaryFile's BinaryFileType requires security, check security //// note: we put a RequiresSecurity flag on BinaryFileType because checking security for every image would be slow (~40ms+ per image request) if (binaryFileMetaData.BinaryFileType_RequiresSecurity) { var currentUser = new UserLoginService(rockContext).GetByUserName(UserLogin.GetCurrentUserName()); Person currentPerson = currentUser != null ? currentUser.Person : null; BinaryFile binaryFileAuth = new BinaryFileService(rockContext).Queryable("BinaryFileType").First(a => a.Guid == fileGuid || a.Id == fileId); if (!binaryFileAuth.IsAuthorized(Authorization.VIEW, currentPerson)) { SendNotAuthorized(context); return; } } byte[] fileContent = null; // Is it cached string cacheName = UrlQueryToCachedFileName(context.Request.QueryString, binaryFileMetaData.MimeType); string physCachedFilePath = context.Request.MapPath(string.Format("~/App_Data/Cache/{0}", cacheName)); if (binaryFileMetaData.BinaryFileType_AllowCaching && File.Exists(physCachedFilePath)) { //// Compare the File's Creation DateTime (which comes from the OS's clock), adjust it for the Rock OrgTimeZone, then compare to BinaryFile's ModifiedDateTime (which is already in OrgTimeZone). //// If the BinaryFile record in the database is less recent than the last time this was cached, it is safe to use the Cached version. //// NOTE: A BinaryFile record is typically just added and never modified (a modify is just creating a new BinaryFile record and deleting the old one), so the cached version will probably always be the correct choice. DateTime cachedFileDateTime = RockDateTime.ConvertLocalDateTimeToRockDateTime(File.GetCreationTime(physCachedFilePath)); if (binaryFileMetaData.ModifiedDateTime < cachedFileDateTime) { // NOTE: the cached file has already been resized (the size is part of the cached file's filename), so we don't need to resize it again fileContent = FetchFromCache(physCachedFilePath); } } if (fileContent == null) { // If we didn't get it from the cache, get it from the binaryFileService BinaryFile binaryFile = GetFromBinaryFileService(context, fileId, fileGuid); if (binaryFile != null && binaryFile.Data != null) { fileContent = binaryFile.Data.Content; } // If we got the image from the binaryFileService, it might need to be resized and cached if (fileContent != null) { // If more than 1 query string param is passed in, assume resize is needed if (context.Request.QueryString.Count > 1) { // if it isn't an SVG file, do a Resize if (binaryFile.MimeType != "image/svg+xml") { fileContent = GetResized(context.Request.QueryString, fileContent); } } if (binaryFileMetaData.BinaryFileType_AllowCaching) { Cache(fileContent, physCachedFilePath); } } } if (fileContent == null) { // if we couldn't get the file from the binaryFileServie or the cache, respond with NotFound SendNotFound(context); return; } // respond with File context.Response.ContentType = binaryFileMetaData.MimeType; context.Response.AddHeader("content-disposition", "inline;filename=" + binaryFileMetaData.FileName); if (binaryFileMetaData.BinaryFileType_AllowCaching) { // if binaryFileType is set to allowcaching, also tell the browser to cache it for 365 days context.Response.Cache.SetLastModified(binaryFileMetaData.ModifiedDateTime); context.Response.Cache.SetMaxAge(new TimeSpan(365, 0, 0, 0)); } context.Response.BinaryWrite(fileContent); context.Response.Flush(); }
/// <summary> /// Processes for recipient. /// </summary> /// <param name="eventType">Type of the event.</param> /// <param name="communicationRecipientGuid">The communication recipient unique identifier.</param> /// <param name="rockContext">The rock context.</param> private void ProcessForReceipent(Guid?communicationRecipientGuid, Rock.Data.RockContext rockContext) { if (!communicationRecipientGuid.HasValue) { return; } var communicationRecipient = new CommunicationRecipientService(rockContext).Get(communicationRecipientGuid.Value); if (communicationRecipient != null && communicationRecipient.Communication != null) { var communicationGuid = Rock.SystemGuid.InteractionChannel.COMMUNICATION.AsGuid(); var interactionComponent = new InteractionComponentService(rockContext) .GetComponentByEntityId(communicationGuid, communicationRecipient.CommunicationId, communicationRecipient.Communication.Subject); rockContext.SaveChanges(); var interactionService = new InteractionService(rockContext); DateTime timeStamp = RockDateTime.ConvertLocalDateTimeToRockDateTime(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(mailgunRequestPayload.TimeStamp).ToLocalTime()); switch (mailgunRequestPayload.EventType) { case "delivered": communicationRecipient.Status = CommunicationRecipientStatus.Delivered; communicationRecipient.StatusNote = string.Format("Confirmed delivered by Mailgun at {0}", timeStamp.ToString()); break; case "opened": communicationRecipient.Status = CommunicationRecipientStatus.Opened; communicationRecipient.OpenedDateTime = timeStamp; communicationRecipient.OpenedClient = string.Format( "{0} {1} ({2})", mailgunRequestPayload.ClientOs ?? "unknown", mailgunRequestPayload.ClientName ?? "unknown", mailgunRequestPayload.DeviceType ?? "unknown"); if (interactionComponent != null) { interactionService.AddInteraction( interactionComponent.Id, communicationRecipient.Id, "Opened", string.Empty, communicationRecipient.PersonAliasId, timeStamp, mailgunRequestPayload.ClientName, mailgunRequestPayload.ClientOs, mailgunRequestPayload.ClientType, mailgunRequestPayload.DeviceType, mailgunRequestPayload.Ip, null); } break; case "clicked": if (interactionComponent != null) { interactionService.AddInteraction( interactionComponent.Id, communicationRecipient.Id, "Click", mailgunRequestPayload.Url, communicationRecipient.PersonAliasId, timeStamp, mailgunRequestPayload.ClientName, mailgunRequestPayload.ClientOs, mailgunRequestPayload.ClientType, mailgunRequestPayload.DeviceType, mailgunRequestPayload.Ip, null); } break; case "complained": break; case "unsubscribed": break; case "dropped": communicationRecipient.Status = CommunicationRecipientStatus.Failed; communicationRecipient.StatusNote = mailgunRequestPayload.Description; break; case "bounced": communicationRecipient.Status = CommunicationRecipientStatus.Failed; communicationRecipient.StatusNote = mailgunRequestPayload.Notification; Rock.Communication.Email.ProcessBounce( mailgunRequestPayload.Recipient, Rock.Communication.BounceType.HardBounce, mailgunRequestPayload.Notification, timeStamp); break; case "failed": // The new mailgun API bundles undeliverable mail into a failed event. The reason (e.g. bounced) is in a seperate property called reason. if (mailgunRequestPayload.EventTypeReason.IsNotNullOrWhiteSpace()) { switch (mailgunRequestPayload.EventTypeReason) { case "bounce": case "suppress-bounce": communicationRecipient.Status = CommunicationRecipientStatus.Failed; communicationRecipient.StatusNote = mailgunRequestPayload.Description; Rock.Communication.Email.ProcessBounce( mailgunRequestPayload.Recipient, Rock.Communication.BounceType.HardBounce, mailgunRequestPayload.Description, timeStamp); break; default: communicationRecipient.Status = CommunicationRecipientStatus.Failed; communicationRecipient.StatusNote = mailgunRequestPayload.Description; break; } } break; } rockContext.SaveChanges(); } }
/// <summary> /// Processes for recipient. /// </summary> /// <param name="eventType">Type of the event.</param> /// <param name="communicationRecipientGuid">The communication recipient unique identifier.</param> /// <param name="rockContext">The rock context.</param> private void ProcessForReceipent(string eventType, Guid?communicationRecipientGuid, Rock.Data.RockContext rockContext) { if (!communicationRecipientGuid.HasValue) { return; } var communicationRecipient = new CommunicationRecipientService(rockContext).Get(communicationRecipientGuid.Value); if (communicationRecipient != null && communicationRecipient.Communication != null) { int secs = request.Form["timestamp"].AsInteger(); DateTime ts = RockDateTime.ConvertLocalDateTimeToRockDateTime(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(secs).ToLocalTime()); var communicationGuid = Rock.SystemGuid.InteractionChannel.COMMUNICATION.AsGuid(); InteractionComponent interactionComponent = new InteractionComponentService(rockContext) .GetComponentByEntityId(communicationGuid, communicationRecipient.CommunicationId, communicationRecipient.Communication.Subject); rockContext.SaveChanges(); var interactionService = new InteractionService(rockContext); switch (eventType) { case "delivered": communicationRecipient.Status = CommunicationRecipientStatus.Delivered; communicationRecipient.StatusNote = string.Format("Confirmed delivered by Mailgun at {0}", ts.ToString()); break; case "opened": communicationRecipient.Status = CommunicationRecipientStatus.Opened; communicationRecipient.OpenedDateTime = ts; communicationRecipient.OpenedClient = string.Format( "{0} {1} ({2})", request.Form["client-os"] ?? "unknown", request.Form["client-name"] ?? "unknown", request.Form["device-type"] ?? "unknown"); if (interactionComponent != null) { interactionService.AddInteraction( interactionComponent.Id, communicationRecipient.Id, "Opened", string.Empty, communicationRecipient.PersonAliasId, ts, request.Form["client-name"], request.Form["client-os"], request.Form["client-type"], request.Form["device-type"], request.Form["ip"], null); } break; case "clicked": if (interactionComponent != null) { interactionService.AddInteraction( interactionComponent.Id, communicationRecipient.Id, "Click", request.Form["url"], communicationRecipient.PersonAliasId, ts, request.Form["client-name"], request.Form["client-os"], request.Form["client-type"], request.Form["device-type"], request.Form["ip"], null); } break; case "complained": break; case "unsubscribed": break; case "dropped": communicationRecipient.Status = CommunicationRecipientStatus.Failed; communicationRecipient.StatusNote = request.Form["description"]; break; case "bounced": communicationRecipient.Status = CommunicationRecipientStatus.Failed; communicationRecipient.StatusNote = request.Form["notification"]; Rock.Communication.Email.ProcessBounce( request.Form["recipient"], Rock.Communication.BounceType.HardBounce, request.Form["notification"], ts); break; } rockContext.SaveChanges(); } }
/// <summary> /// Processes for recipient. /// </summary> /// <param name="eventType">Type of the event.</param> /// <param name="communicationRecipientGuid">The communication recipient unique identifier.</param> /// <param name="rockContext">The rock context.</param> private void ProcessForRecipient(Guid?communicationRecipientGuid, Rock.Data.RockContext rockContext, SendGridEvent payload) { RockLogger.Log.Debug(RockLogDomains.Communications, "ProcessForRecipient {@payload}", payload); if (!communicationRecipientGuid.HasValue) { return; } var communicationRecipient = new CommunicationRecipientService(rockContext).Get(communicationRecipientGuid.Value); if (communicationRecipient != null && communicationRecipient.Communication != null) { var communicationGuid = Rock.SystemGuid.InteractionChannel.COMMUNICATION.AsGuid(); var interactionComponent = new InteractionComponentService(rockContext) .GetComponentByEntityId(communicationGuid, communicationRecipient.CommunicationId, communicationRecipient.Communication.Subject); rockContext.SaveChanges(); var interactionService = new InteractionService(rockContext); DateTime timeStamp = RockDateTime.ConvertLocalDateTimeToRockDateTime(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(payload.Timestamp).ToLocalTime()); switch (payload.EventType) { case "processed": // Do nothing. break; case "dropped": communicationRecipient.Status = CommunicationRecipientStatus.Failed; communicationRecipient.StatusNote = payload.EventTypeReason; if (payload.EventTypeReason == "Bounced Address") { Rock.Communication.Email.ProcessBounce( payload.Email, Rock.Communication.BounceType.HardBounce, payload.EventTypeReason, timeStamp); } break; case "delivered": communicationRecipient.Status = CommunicationRecipientStatus.Delivered; communicationRecipient.StatusNote = string.Format("Confirmed delivered by SendGrid at {0}", timeStamp.ToString()); break; case "deferred": // TODO: handle deferred. break; case "bounce": communicationRecipient.Status = CommunicationRecipientStatus.Failed; communicationRecipient.StatusNote = payload.EventTypeReason + payload.ServerResponse; Rock.Communication.Email.ProcessBounce( payload.Email, Rock.Communication.BounceType.HardBounce, payload.EventTypeReason, timeStamp); break; case "blocked": // TODO: handle blocked. break; case "open": communicationRecipient.Status = CommunicationRecipientStatus.Opened; communicationRecipient.OpenedDateTime = timeStamp; communicationRecipient.OpenedClient = string.Format( "{0} {1} ({2})", payload.ClientOs ?? "unknown", payload.ClientBrowser ?? "unknown", payload.ClientDeviceType ?? "unknown"); if (interactionComponent != null) { interactionService.AddInteraction( interactionComponent.Id, communicationRecipient.Id, "Opened", payload.SendGridEventId, communicationRecipient.PersonAliasId, timeStamp, payload.ClientBrowser, payload.ClientOs, payload.ClientDeviceType, payload.ClientDeviceBrand, payload.IpAddress, null); } break; case "click": if (interactionComponent != null) { interactionService.AddInteraction( interactionComponent.Id, communicationRecipient.Id, "Click", payload.Url, communicationRecipient.PersonAliasId, timeStamp, payload.ClientBrowser, payload.ClientOs, payload.ClientDeviceType, payload.ClientDeviceBrand, payload.IpAddress, null); } break; case "spamreport": case "unsubscribe": case "group_unsubscribe": case "group_resubscribe": // Do nothing. break; } rockContext.SaveChanges(); } }
/// <summary> /// Sets the RockDateTime timezone to the current system local timezone. /// </summary> public static void SetRockDateTimeToLocalTimezone() { RockDateTime.Initialize(TimeZoneInfo.Local); }
/// <summary> /// Sets the RockDateTime timezone to the current system local timezone. /// </summary> public static void SetRockOrganizationLocalTimeZone() { RockDateTime.Initialize(TimeZoneInfo.Local); }
public IHttpActionResult PostInteractions([FromBody] List <MobileInteractionSession> sessions, Guid?personalDeviceGuid = null) { var person = GetPerson(); var ipAddress = System.Web.HttpContext.Current?.Request?.UserHostAddress; using (var rockContext = new Data.RockContext()) { var interactionChannelService = new InteractionChannelService(rockContext); var interactionComponentService = new InteractionComponentService(rockContext); var interactionSessionService = new InteractionSessionService(rockContext); var interactionService = new InteractionService(rockContext); var userLoginService = new UserLoginService(rockContext); var channelMediumTypeValue = DefinedValueCache.Get(SystemGuid.DefinedValue.INTERACTIONCHANNELTYPE_WEBSITE); var pageEntityTypeId = EntityTypeCache.Get(typeof(Model.Page)).Id; // // Check to see if we have a site and the API key is valid. // if (MobileHelper.GetCurrentApplicationSite() == null) { return(StatusCode(System.Net.HttpStatusCode.Forbidden)); } // // Get the personal device identifier if they provided it's unique identifier. // int?personalDeviceId = null; if (personalDeviceGuid.HasValue) { personalDeviceId = new PersonalDeviceService(rockContext).GetId(personalDeviceGuid.Value); } // // Create a quick way to cache data since we have to loop twice. // var interactionComponentLookup = new Dictionary <string, int>(); // // Helper method to get a cache key for looking up the component Id. // string GetComponentCacheKey(MobileInteraction mi) { return($"{mi.AppId}:{mi.PageGuid}:{mi.ChannelGuid}:{mi.ChannelId}:{mi.ComponentId}:{mi.ComponentName}"); } // // Interactions Components will now try to load from cache which // causes problems if we are inside a transaction. So first loop through // everything and make sure all our components and channels exist. // var prePassInteractions = sessions.SelectMany(a => a.Interactions) .DistinctBy(a => GetComponentCacheKey(a)); // // It's safe to do this pre-pass outside the transaction since we are just creating // the channels and components (if necessary), which is going to have to be done at // at some point no matter what. // foreach (var mobileInteraction in prePassInteractions) { // // Lookup the interaction channel, and create it if it doesn't exist // if (mobileInteraction.AppId.HasValue && mobileInteraction.PageGuid.HasValue) { var site = SiteCache.Get(mobileInteraction.AppId.Value); var page = PageCache.Get(mobileInteraction.PageGuid.Value); if (site == null || page == null) { continue; } // // Try to find an existing interaction channel. // var interactionChannelId = InteractionChannelCache.GetChannelIdByTypeIdAndEntityId(channelMediumTypeValue.Id, site.Id, site.Name, pageEntityTypeId, null); // // Get an existing or create a new component. // var interactionComponentId = InteractionComponentCache.GetComponentIdByChannelIdAndEntityId(interactionChannelId, page.Id, page.InternalName); interactionComponentLookup.AddOrReplace(GetComponentCacheKey(mobileInteraction), interactionComponentId); } else if (mobileInteraction.ChannelId.HasValue || mobileInteraction.ChannelGuid.HasValue) { int?interactionChannelId = null; if (mobileInteraction.ChannelId.HasValue) { interactionChannelId = mobileInteraction.ChannelId.Value; } else if (mobileInteraction.ChannelGuid.HasValue) { interactionChannelId = InteractionChannelCache.Get(mobileInteraction.ChannelGuid.Value)?.Id; } if (interactionChannelId.HasValue) { if (mobileInteraction.ComponentId.HasValue) { // Use the provided component identifier. interactionComponentLookup.AddOrReplace(GetComponentCacheKey(mobileInteraction), mobileInteraction.ComponentId.Value); } else if (mobileInteraction.ComponentName.IsNotNullOrWhiteSpace()) { int interactionComponentId; // Get or create a new component with the details we have. if (mobileInteraction.ComponentEntityId.HasValue) { interactionComponentId = InteractionComponentCache.GetComponentIdByChannelIdAndEntityId(interactionChannelId.Value, mobileInteraction.ComponentEntityId, mobileInteraction.ComponentName); } else { var interactionComponent = interactionComponentService.GetComponentByComponentName(interactionChannelId.Value, mobileInteraction.ComponentName); rockContext.SaveChanges(); interactionComponentId = interactionComponent.Id; } interactionComponentLookup.AddOrReplace(GetComponentCacheKey(mobileInteraction), interactionComponentId); } } } } // // Now wrap the actual interaction creation inside a transaction. We should // probably move this so it uses the InteractionTransaction class for better // performance. This is so we can inform the client that either everything // saved or that nothing saved. No partial saves here. // rockContext.WrapTransaction(() => { foreach (var mobileSession in sessions) { var interactionGuids = mobileSession.Interactions.Select(i => i.Guid).ToList(); var existingInteractionGuids = interactionService.Queryable() .Where(i => interactionGuids.Contains(i.Guid)) .Select(i => i.Guid) .ToList(); // // Loop through all interactions that don't already exist and add each one. // foreach (var mobileInteraction in mobileSession.Interactions.Where(i => !existingInteractionGuids.Contains(i.Guid))) { string cacheKey = GetComponentCacheKey(mobileInteraction); if (!interactionComponentLookup.ContainsKey(cacheKey)) { // Shouldn't happen, but just in case. continue; } var interactionComponentId = interactionComponentLookup[cacheKey]; // // Add the interaction // var interaction = interactionService.CreateInteraction(interactionComponentId, mobileInteraction.EntityId, mobileInteraction.Operation, mobileInteraction.Summary, mobileInteraction.Data, person?.PrimaryAliasId, RockDateTime.ConvertLocalDateTimeToRockDateTime(mobileInteraction.DateTime.LocalDateTime), mobileSession.Application, mobileSession.OperatingSystem, mobileSession.ClientType, null, ipAddress, mobileSession.Guid); interaction.Guid = mobileInteraction.Guid; interaction.PersonalDeviceId = personalDeviceId; interaction.RelatedEntityTypeId = mobileInteraction.RelatedEntityTypeId; interaction.RelatedEntityId = mobileInteraction.RelatedEntityId; interaction.ChannelCustom1 = mobileInteraction.ChannelCustom1; interaction.ChannelCustom2 = mobileInteraction.ChannelCustom2; interaction.ChannelCustomIndexed1 = mobileInteraction.ChannelCustomIndexed1; interactionService.Add(interaction); // Attempt to process this as a communication interaction. ProcessCommunicationInteraction(mobileSession, mobileInteraction, rockContext); } } rockContext.SaveChanges(); }); } return(Ok()); }
public void Execute(IJobExecutionContext context) { var rockContext = new RockContext(); var dataMap = context.JobDetail.JobDataMap; DateTime?lastRun = null; if (context.PreviousFireTimeUtc.HasValue) { lastRun = RockDateTime.ConvertLocalDateTimeToRockDateTime(context.PreviousFireTimeUtc.Value.LocalDateTime); } var systemEmailGuid = dataMap.GetString("Email").AsGuidOrNull(); string appRoot = Rock.Web.Cache.GlobalAttributesCache.Read().GetValue("PublicApplicationRoot"); if (appRoot.IsNullOrWhiteSpace()) { throw new Exception("Couldn't fetch application root!"); } if (systemEmailGuid == null) { throw new Exception("A system email template needs to be set."); } var systemEmailTemplate = new SystemEmailService(rockContext).Get(systemEmailGuid.Value); if (systemEmailTemplate == null) { throw new Exception("The system email template setting is not a valid system email template."); } var cutOffHours = dataMap.GetString("IncludeHours").AsIntegerOrNull(); if (!cutOffHours.HasValue) { throw new Exception("A cutoff period needs to be set."); } if (lastRun == null) { lastRun = RockDateTime.Now.AddHours(-1 * cutOffHours.Value); } var connectionRequestService = new ConnectionRequestService(rockContext); var openConnectionRequests = connectionRequestService.Queryable() .AsNoTracking() .Where(cr => cr.CreatedDateTime >= lastRun && cr.ConnectionState != ConnectionState.Connected && cr.ConnectorPersonAliasId != null); if (!openConnectionRequests.Any()) { context.Result = "There are no open and assigned connection requests to send alerts for"; return; } var groupedRequests = openConnectionRequests .ToList() .GroupBy(cr => cr.ConnectorPersonAlias); int mailedCount = 0; foreach (var connectionRequestGrouping in groupedRequests) { if (connectionRequestGrouping.Key == null) { continue; } var connectionRequests = connectionRequestGrouping.ToList(); var mergeFields = new Dictionary <string, object> { { "ConnectionRequests", connectionRequests }, { "Person", connectionRequestGrouping.Key.Person } }; var recipients = new List <string> { connectionRequestGrouping.Key.Person.Email }; Email.Send(systemEmailTemplate.From.ResolveMergeFields(mergeFields), systemEmailTemplate.FromName.ResolveMergeFields(mergeFields), systemEmailTemplate.Subject.ResolveMergeFields(mergeFields), recipients, systemEmailTemplate.Body.ResolveMergeFields(mergeFields), appRoot, null); mailedCount++; } context.Result = string.Format("{0} reminders were sent ", mailedCount); }