public IHttpActionResult Login([FromBody] LoginParameters loginParameters) { var authController = new AuthController(); var site = MobileHelper.GetCurrentApplicationSite(); if (site == null) { return(StatusCode(System.Net.HttpStatusCode.Unauthorized)); } // // Chain to the existing login method for actual authorization check. // Throws exception if not authorized. // authController.Login(loginParameters); // // Find the user and translate to a mobile person. // var userLoginService = new UserLoginService(new Rock.Data.RockContext()); var userLogin = userLoginService.GetByUserName(loginParameters.Username); var mobilePerson = MobileHelper.GetMobilePerson(userLogin.Person, site); mobilePerson.AuthToken = MobileHelper.GetAuthenticationToken(loginParameters.Username); return(Ok(mobilePerson)); }
public IHttpActionResult Login([FromBody] LoginParameters loginParameters, Guid?personalDeviceGuid = null) { var site = MobileHelper.GetCurrentApplicationSite(); if (site == null) { return(StatusCode(System.Net.HttpStatusCode.Unauthorized)); } // // Use the existing AuthController.IsLoginValid method for actual authorization check. Throws exception if not authorized. // if (!AuthController.IsLoginValid(loginParameters, out var errorMessage, out var userName)) { var errorResponse = ControllerContext.Request.CreateErrorResponse(System.Net.HttpStatusCode.Unauthorized, errorMessage); throw new HttpResponseException(errorResponse); } // // Find the user and translate to a mobile person. // using (var rockContext = new Rock.Data.RockContext()) { var userLoginService = new UserLoginService(rockContext); var userLogin = userLoginService.GetByUserName(loginParameters.Username); if (personalDeviceGuid.HasValue) { var personalDevice = new PersonalDeviceService(rockContext).Get(personalDeviceGuid.Value); if (personalDevice != null && personalDevice.PersonAliasId != userLogin.Person.PrimaryAliasId) { personalDevice.PersonAliasId = userLogin.Person.PrimaryAliasId; } } userLogin.LastLoginDateTime = RockDateTime.Now; rockContext.SaveChanges(); var mobilePerson = MobileHelper.GetMobilePerson(userLogin.Person, site); mobilePerson.AuthToken = MobileHelper.GetAuthenticationToken(loginParameters.Username); return(Ok(mobilePerson)); } }
public object GetLaunchPacket() { var baseUrl = GlobalAttributesCache.Value("PublicApplicationRoot"); var site = MobileHelper.GetCurrentApplicationSite(); var additionalSettings = site?.AdditionalSettings.FromJsonOrNull <AdditionalSiteSettings>(); var person = GetPerson(); var deviceData = Request.GetHeader("X-Rock-DeviceData").FromJsonOrNull <DeviceData>(); if (additionalSettings == null || !additionalSettings.LastDeploymentDate.HasValue) { return(NotFound()); } var launchPacket = new LaunchPackage { LatestVersionId = ( int )(additionalSettings.LastDeploymentDate.Value.ToJavascriptMilliseconds() / 1000), IsSiteAdministrator = site.IsAuthorized(Authorization.EDIT, person) }; if (deviceData.DeviceType == DeviceType.Phone) { launchPacket.LatestVersionSettingsUrl = additionalSettings.PhoneUpdatePackageUrl; } else if (deviceData.DeviceType == DeviceType.Tablet) { launchPacket.LatestVersionSettingsUrl = additionalSettings.TabletUpdatePackageUrl; } else { return(NotFound()); } if (person != null) { var principal = ControllerContext.Request.GetUserPrincipal(); launchPacket.CurrentPerson = MobileHelper.GetMobilePerson(person, site); launchPacket.CurrentPerson.AuthToken = MobileHelper.GetAuthenticationToken(principal.Identity.Name); } return(launchPacket); }
/// <summary> /// Gets the response to send for a valid login on mobile. /// </summary> /// <param name="userLogin">The user login.</param> /// <param name="rememberMe">if set to <c>true</c> then the login should persist beyond this session.</param> /// <returns>The result of the action.</returns> private BlockActionResult GetMobileResponse(UserLogin userLogin, bool rememberMe) { var site = MobileHelper.GetCurrentApplicationSite(); if (site == null) { return(ActionStatusCode(HttpStatusCode.Unauthorized)); } var authCookie = Rock.Security.Authorization.GetSimpleAuthCookie(userLogin.UserName, rememberMe, false); var mobilePerson = MobileHelper.GetMobilePerson(userLogin.Person, site); mobilePerson.AuthToken = authCookie.Value; return(ActionOk(new { Person = mobilePerson })); }
public IHttpActionResult Login([FromBody] LoginParameters loginParameters, Guid?personalDeviceGuid = null) { var authController = new AuthController(); var site = MobileHelper.GetCurrentApplicationSite(); if (site == null) { return(StatusCode(System.Net.HttpStatusCode.Unauthorized)); } // // Chain to the existing login method for actual authorization check. // Throws exception if not authorized. // authController.Login(loginParameters); // // Find the user and translate to a mobile person. // using (var rockContext = new Rock.Data.RockContext()) { var userLoginService = new UserLoginService(rockContext); var userLogin = userLoginService.GetByUserName(loginParameters.Username); if (personalDeviceGuid.HasValue) { var personalDevice = new PersonalDeviceService(rockContext).Get(personalDeviceGuid.Value); if (personalDevice != null && personalDevice.PersonAliasId != userLogin.Person.PrimaryAliasId) { personalDevice.PersonAliasId = userLogin.Person.PrimaryAliasId; rockContext.SaveChanges(); } } var mobilePerson = MobileHelper.GetMobilePerson(userLogin.Person, site); mobilePerson.AuthToken = MobileHelper.GetAuthenticationToken(loginParameters.Username); return(Ok(mobilePerson)); } }
/// <summary> /// Writes the opened interaction. /// </summary> /// <param name="rockContext">The rock context.</param> /// <param name="recipient">The recipient.</param> private void WriteInteraction(RockContext rockContext, CommunicationRecipient recipient) { var interactionService = new InteractionService(rockContext); InteractionComponent interactionComponent = new InteractionComponentService(rockContext) .GetComponentByEntityId(Rock.SystemGuid.InteractionChannel.COMMUNICATION.AsGuid(), recipient.Communication.Id, recipient.Communication.Subject); rockContext.SaveChanges(); var clientType = "None"; var clientOs = string.Empty; var ipAddress = RequestContext.ClientInformation.IpAddress; var site = MobileHelper.GetCurrentApplicationSite(false, rockContext); var siteName = site?.Name ?? "Unknown"; var now = RockDateTime.Now; // // Determine if this is a phone or tablet. // var deviceData = RequestContext.GetHeader("X-Rock-DeviceData") .FirstOrDefault() ?.FromJsonOrNull <DeviceData>(); if (deviceData != null) { clientType = deviceData.DeviceType == Common.Mobile.Enums.DeviceType.Phone ? "Mobile" : "Tablet"; clientOs = deviceData.DevicePlatform.ToString(); } recipient.Status = CommunicationRecipientStatus.Opened; recipient.OpenedDateTime = now; recipient.OpenedClient = $"{clientOs} {siteName} ({clientType})"; interactionService.AddInteraction(interactionComponent.Id, recipient.Id, "Opened", "", recipient.PersonAliasId, now, siteName, clientOs, clientType, string.Empty, ipAddress, null); rockContext.SaveChanges(); }
public IHttpActionResult GetLaunchPacket(string deviceIdentifier = null) { var site = MobileHelper.GetCurrentApplicationSite(); var additionalSettings = site?.AdditionalSettings.FromJsonOrNull <AdditionalSiteSettings>(); var rockContext = new Rock.Data.RockContext(); var person = GetPerson(rockContext); var deviceData = Request.GetHeader("X-Rock-DeviceData").FromJsonOrNull <DeviceData>(); if (additionalSettings == null || !additionalSettings.LastDeploymentDate.HasValue) { return(NotFound()); } var launchPacket = new LaunchPacket { LatestVersionId = ( int )(additionalSettings.LastDeploymentDate.Value.ToJavascriptMilliseconds() / 1000), IsSiteAdministrator = site.IsAuthorized(Authorization.EDIT, person) }; if (deviceData.DeviceType == DeviceType.Phone) { launchPacket.LatestVersionSettingsUrl = additionalSettings.PhoneUpdatePackageUrl; } else if (deviceData.DeviceType == DeviceType.Tablet) { launchPacket.LatestVersionSettingsUrl = additionalSettings.TabletUpdatePackageUrl; } else { return(NotFound()); } if (person != null) { var principal = ControllerContext.Request.GetUserPrincipal(); launchPacket.CurrentPerson = MobileHelper.GetMobilePerson(person, site); launchPacket.CurrentPerson.AuthToken = MobileHelper.GetAuthenticationToken(principal.Identity.Name); } // // Get or create the personal device. // if (deviceIdentifier.IsNotNullOrWhiteSpace()) { var mobileDeviceTypeValueId = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.PERSONAL_DEVICE_TYPE_MOBILE).Id; var personalDeviceService = new PersonalDeviceService(rockContext); var personalDevice = personalDeviceService.Queryable() .AsNoTracking() .Where(a => a.DeviceUniqueIdentifier == deviceIdentifier && a.PersonalDeviceTypeValueId == mobileDeviceTypeValueId) .FirstOrDefault(); if (personalDevice == null) { personalDevice = new PersonalDevice { DeviceUniqueIdentifier = deviceIdentifier, PersonalDeviceTypeValueId = mobileDeviceTypeValueId, PlatformValueId = deviceData.DevicePlatform.GetDevicePlatformValueId(), PersonAliasId = person?.PrimaryAliasId, NotificationsEnabled = true }; personalDeviceService.Add(personalDevice); rockContext.SaveChanges(); } launchPacket.PersonalDeviceGuid = personalDevice.Guid; } return(Ok(launchPacket)); }
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); } 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))) { int?interactionComponentId = null; // // 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 = interactionChannelService.Queryable() .Where(a => a.ChannelTypeMediumValueId == channelMediumTypeValue.Id && a.ChannelEntityId == site.Id) .Select(a => ( int? )a.Id) .FirstOrDefault(); // // If not found, create one. // if (!interactionChannelId.HasValue) { var interactionChannel = new InteractionChannel { Name = site.Name, ChannelTypeMediumValueId = channelMediumTypeValue.Id, ChannelEntityId = site.Id, ComponentEntityTypeId = pageEntityTypeId }; interactionChannelService.Add(interactionChannel); rockContext.SaveChanges(); interactionChannelId = interactionChannel.Id; } // // Get an existing or create a new component. // var interactionComponent = interactionComponentService.GetComponentByChannelIdAndEntityId(interactionChannelId.Value, page.Id, page.InternalName); rockContext.SaveChanges(); interactionComponentId = interactionComponent.Id; } else if (mobileInteraction.ChannelId.HasValue) { var interactionChannelId = mobileInteraction.ChannelId; if (mobileInteraction.ComponentId.HasValue) { interactionComponentId = mobileInteraction.ComponentId.Value; } else if (mobileInteraction.ComponentName.IsNotNullOrWhiteSpace()) { // // Get an existing or create a new component. // var interactionComponent = interactionComponentService.GetComponentByComponentName(interactionChannelId.Value, mobileInteraction.ComponentName); rockContext.SaveChanges(); interactionComponentId = interactionComponent.Id; } else { continue; } } else { continue; } // // Add the interaction // if (interactionComponentId.HasValue) { var interaction = interactionService.CreateInteraction(interactionComponentId.Value, mobileInteraction.EntityId, mobileInteraction.Operation, mobileInteraction.Summary, mobileInteraction.Data, person?.PrimaryAliasId, mobileInteraction.DateTime, mobileSession.Application, mobileSession.OperatingSystem, mobileSession.ClientType, null, ipAddress, mobileSession.Guid); interaction.Guid = mobileInteraction.Guid; interaction.PersonalDeviceId = personalDeviceId; interactionService.Add(interaction); rockContext.SaveChanges(); } } } }); } return(Ok()); }
public object UpdateProfile(MobilePerson profile) { var user = UserLoginService.GetCurrentUser(false); if (user == null) { return(ActionStatusCode(System.Net.HttpStatusCode.Unauthorized)); } var personId = user.PersonId.Value; var rockContext = new Data.RockContext(); var personService = new PersonService(rockContext); var phoneNumberService = new PhoneNumberService(rockContext); var person = personService.Get(personId); person.NickName = person.NickName == person.FirstName ? profile.FirstName : person.NickName; person.FirstName = profile.FirstName; person.LastName = profile.LastName; var gender = (Model.Gender)profile.Gender; if (GenderVisibility != VisibilityTriState.Hidden) { person.Gender = gender; } if (GetAttributeValue(AttributeKeys.BirthDateShow).AsBoolean()) { person.SetBirthDate(profile.BirthDate?.Date); } if (GetAttributeValue(AttributeKeys.CampusShow).AsBoolean()) { person.PrimaryFamily.CampusId = profile.CampusGuid.HasValue ? CampusCache.Get(profile.CampusGuid.Value)?.Id : null; } if (GetAttributeValue(AttributeKeys.EmailShow).AsBoolean()) { person.Email = profile.Email; } if (GetAttributeValue(AttributeKeys.MobilePhoneShow).AsBoolean()) { int phoneNumberTypeId = DefinedValueCache.Get(SystemGuid.DefinedValue.PERSON_PHONE_TYPE_MOBILE).Id; var phoneNumber = person.PhoneNumbers.FirstOrDefault(n => n.NumberTypeValueId == phoneNumberTypeId); if (phoneNumber == null) { phoneNumber = new PhoneNumber { NumberTypeValueId = phoneNumberTypeId }; person.PhoneNumbers.Add(phoneNumber); } // TODO: What to do with country code? phoneNumber.CountryCode = PhoneNumber.CleanNumber("+1"); phoneNumber.Number = PhoneNumber.CleanNumber(profile.MobilePhone); if (string.IsNullOrWhiteSpace(phoneNumber.Number)) { person.PhoneNumbers.Remove(phoneNumber); phoneNumberService.Delete(phoneNumber); } } if (GetAttributeValue(AttributeKeys.AddressShow).AsBoolean()) { var addressTypeGuid = SystemGuid.DefinedValue.GROUP_LOCATION_TYPE_HOME.AsGuid(); var groupLocationService = new GroupLocationService(rockContext); var dvHomeAddressType = DefinedValueCache.Get(addressTypeGuid); var familyAddress = groupLocationService.Queryable().Where(l => l.GroupId == person.PrimaryFamily.Id && l.GroupLocationTypeValueId == dvHomeAddressType.Id).FirstOrDefault(); if (familyAddress != null && string.IsNullOrWhiteSpace(profile.HomeAddress.Street1)) { // delete the current address groupLocationService.Delete(familyAddress); } else { if (!string.IsNullOrWhiteSpace(profile.HomeAddress.Street1)) { if (familyAddress == null) { familyAddress = new GroupLocation(); groupLocationService.Add(familyAddress); familyAddress.GroupLocationTypeValueId = dvHomeAddressType.Id; familyAddress.GroupId = person.PrimaryFamily.Id; familyAddress.IsMailingLocation = true; familyAddress.IsMappedLocation = true; } else if (familyAddress.Location.Street1 != profile.HomeAddress.Street1) { // user clicked move so create a previous address var previousAddress = new GroupLocation(); groupLocationService.Add(previousAddress); var previousAddressValue = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.GROUP_LOCATION_TYPE_PREVIOUS.AsGuid()); if (previousAddressValue != null) { previousAddress.GroupLocationTypeValueId = previousAddressValue.Id; previousAddress.GroupId = person.PrimaryFamily.Id; Location previousAddressLocation = new Location { Street1 = familyAddress.Location.Street1, Street2 = familyAddress.Location.Street2, City = familyAddress.Location.City, State = familyAddress.Location.State, PostalCode = familyAddress.Location.PostalCode, Country = familyAddress.Location.Country }; previousAddress.Location = previousAddressLocation; } } // TODO: ??? // familyAddress.IsMailingLocation = cbIsMailingAddress.Checked; // familyAddress.IsMappedLocation = cbIsPhysicalAddress.Checked; familyAddress.Location = new LocationService(rockContext).Get( profile.HomeAddress.Street1, string.Empty, profile.HomeAddress.City, profile.HomeAddress.State, profile.HomeAddress.PostalCode, profile.HomeAddress.Country, person.PrimaryFamily, true); // since there can only be one mapped location, set the other locations to not mapped if (familyAddress.IsMappedLocation) { var groupLocations = groupLocationService.Queryable() .Where(l => l.GroupId == person.PrimaryFamily.Id && l.Id != familyAddress.Id).ToList(); foreach (var groupLocation in groupLocations) { groupLocation.IsMappedLocation = false; } } rockContext.SaveChanges(); } } } rockContext.SaveChanges(); var mobilePerson = MobileHelper.GetMobilePerson(person, MobileHelper.GetCurrentApplicationSite()); mobilePerson.AuthToken = MobileHelper.GetAuthenticationToken(user.UserName); return(ActionOk(mobilePerson)); }
public IHttpActionResult GetLaunchPacket(string deviceIdentifier = null, bool?notificationsEnabled = null) { var site = MobileHelper.GetCurrentApplicationSite(); var additionalSettings = site?.AdditionalSettings.FromJsonOrNull <AdditionalSiteSettings>(); var rockContext = new Rock.Data.RockContext(); var person = GetPerson(rockContext); var deviceData = Request.GetHeader("X-Rock-DeviceData").FromJsonOrNull <DeviceData>(); if (additionalSettings == null || !additionalSettings.LastDeploymentDate.HasValue) { return(NotFound()); } // Ensure the user login is still active, otherwise log them out. var principal = ControllerContext.Request.GetUserPrincipal(); if (person != null && !principal.Identity.Name.StartsWith("rckipid=")) { var userLogin = new UserLoginService(rockContext).GetByUserName(principal.Identity.Name); if (userLogin?.IsConfirmed != true || userLogin?.IsLockedOut == true) { person = null; } } var launchPacket = new LaunchPacket { RockVersion = Rock.VersionInfo.VersionInfo.GetRockProductVersionNumber(), LatestVersionId = additionalSettings.LastDeploymentVersionId ?? ( int )(additionalSettings.LastDeploymentDate.Value.ToJavascriptMilliseconds() / 1000), IsSiteAdministrator = site.IsAuthorized(Rock.Security.Authorization.EDIT, person) }; if (deviceData.DeviceType == DeviceType.Phone) { launchPacket.LatestVersionSettingsUrl = additionalSettings.PhoneUpdatePackageUrl; } else if (deviceData.DeviceType == DeviceType.Tablet) { launchPacket.LatestVersionSettingsUrl = additionalSettings.TabletUpdatePackageUrl; } else { return(NotFound()); } if (person != null) { //var principal = ControllerContext.Request.GetUserPrincipal(); launchPacket.CurrentPerson = MobileHelper.GetMobilePerson(person, site); launchPacket.CurrentPerson.AuthToken = MobileHelper.GetAuthenticationToken(principal.Identity.Name); UserLoginService.UpdateLastLogin(principal.Identity.Name); } // // Get or create the personal device. // if (deviceIdentifier.IsNotNullOrWhiteSpace()) { var mobileDeviceTypeValueId = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.PERSONAL_DEVICE_TYPE_MOBILE).Id; var personalDeviceService = new PersonalDeviceService(rockContext); var personalDevice = personalDeviceService.Queryable() .Where(a => a.DeviceUniqueIdentifier == deviceIdentifier && a.PersonalDeviceTypeValueId == mobileDeviceTypeValueId && a.SiteId == site.Id) .FirstOrDefault(); if (personalDevice == null) { personalDevice = new PersonalDevice { DeviceUniqueIdentifier = deviceIdentifier, PersonalDeviceTypeValueId = mobileDeviceTypeValueId, SiteId = site.Id, PlatformValueId = deviceData.DevicePlatform.GetDevicePlatformValueId(), PersonAliasId = person?.PrimaryAliasId, NotificationsEnabled = true, Manufacturer = deviceData.Manufacturer, Model = deviceData.Model, Name = deviceData.Name, LastSeenDateTime = RockDateTime.Now }; personalDeviceService.Add(personalDevice); rockContext.SaveChanges(); } else { // A change is determined as one of the following: // 1) A change in Name, Manufacturer, Model, or NotificationsEnabled. // 2) Device not being active. // 3) Not seen in 24 hours. // 4) Signed in with a different person. var hasDeviceChanged = !personalDevice.IsActive || personalDevice.Name != deviceData.Name || personalDevice.Manufacturer != deviceData.Manufacturer || personalDevice.Model != deviceData.Model || personalDevice.NotificationsEnabled != (notificationsEnabled ?? true) || !personalDevice.LastSeenDateTime.HasValue || personalDevice.LastSeenDateTime.Value.AddDays(1) < RockDateTime.Now || (person != null && personalDevice.PersonAliasId != person.PrimaryAliasId); if (hasDeviceChanged) { personalDevice.IsActive = true; personalDevice.Manufacturer = deviceData.Manufacturer; personalDevice.Model = deviceData.Model; personalDevice.Name = deviceData.Name; personalDevice.LastSeenDateTime = RockDateTime.Now; if (notificationsEnabled.HasValue) { personalDevice.NotificationsEnabled = notificationsEnabled.Value; } // Update the person tied to the device, but never blank it out. if (person != null && personalDevice.PersonAliasId != person.PrimaryAliasId) { personalDevice.PersonAliasId = person.PrimaryAliasId; } rockContext.SaveChanges(); } } launchPacket.PersonalDeviceGuid = personalDevice.Guid; } return(Ok(launchPacket)); }
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()); }