public IHttpActionResult GetLaunchPacket() { // Read site Id from the request header var siteId = this.Request.GetHeader("X-Rock-App-Id").AsIntegerOrNull(); // Get device data from the request header // Get device data var deviceData = JsonConvert.DeserializeObject <DeviceData>(this.Request.GetHeader("X-Rock-DeviceData")); if (deviceData == null) { StatusCode(HttpStatusCode.InternalServerError); } if (!siteId.HasValue) { return(NotFound()); } var site = SiteCache.Get(siteId.Value); // If the site was not found then return 404 if (site == null) { return(NotFound()); } // Return the launch packet try { var rockContext = new RockContext(); var person = GetPerson(rockContext); var launchPacket = new AppleLaunchPacket(); launchPacket.EnablePageViews = site.EnablePageViews; if (person != null) { var principal = ControllerContext.Request.GetUserPrincipal(); launchPacket.CurrentPerson = TvHelper.GetTvPerson(person); launchPacket.CurrentPerson.AuthToken = TvHelper.GetAuthenticationTokenFromUsername(principal.Identity.Name); UserLoginService.UpdateLastLogin(principal.Identity.Name); } // Get or create the personal device. var tvDeviceTypeValueId = DefinedValueCache.Get(SystemGuid.DefinedValue.PERSONAL_DEVICE_TYPE_TV).Id; var personalDeviceService = new PersonalDeviceService(rockContext); var personalDevice = personalDeviceService.Queryable() .Where(a => a.DeviceUniqueIdentifier == deviceData.DeviceIdentifier && a.PersonalDeviceTypeValueId == tvDeviceTypeValueId && a.SiteId == site.Id) .FirstOrDefault(); if (personalDevice == null) { personalDevice = new PersonalDevice { DeviceUniqueIdentifier = deviceData.DeviceIdentifier, PersonalDeviceTypeValueId = tvDeviceTypeValueId, SiteId = site.Id, PersonAliasId = person?.PrimaryAliasId, NotificationsEnabled = true, Manufacturer = deviceData.Manufacturer, Model = deviceData.Model, Name = deviceData.Name, IsActive = true, LastSeenDateTime = RockDateTime.Now, DeviceVersion = deviceData.Version }; 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.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; // 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; launchPacket.HomepageGuid = site.DefaultPage.Guid; launchPacket.RockVersion = VersionInfo.VersionInfo.GetRockProductVersionNumber(); return(Ok(launchPacket)); } catch (Exception) { // Ooops... return(StatusCode(HttpStatusCode.InternalServerError)); } }
public HttpResponseMessage CheckAuthenicationSession(int siteId, string code) { var response = new HttpResponseMessage(); var authCheckResponse = new AuthCodeCheckResponse(); var deviceData = JsonConvert.DeserializeObject <DeviceData>(this.Request.GetHeader("X-Rock-DeviceData")); var rockContext = new RockContext(); var remoteAuthenticationSessionService = new RemoteAuthenticationSessionService(rockContext); // Get client Ip address var clientIp = GetClientIp(Request); var expireDateTime = RockDateTime.Now.AddMinutes(_codeReusePeriodInMinutes); // Check for validated account var validatedSession = remoteAuthenticationSessionService.Queryable() .Include(s => s.AuthorizedPersonAlias.Person) .Where(s => s.Code == code && s.SiteId == siteId && s.SessionStartDateTime < expireDateTime && s.AuthorizedPersonAliasId.HasValue && s.DeviceUniqueIdentifier == deviceData.DeviceIdentifier && s.ClientIpAddress == clientIp) .OrderByDescending(s => s.SessionStartDateTime) .FirstOrDefault(); if (validatedSession != null) { // Mark the auth session as ended validatedSession.SessionEndDateTime = RockDateTime.Now; rockContext.SaveChanges(); authCheckResponse.CurrentPerson = TvHelper.GetTvPerson(validatedSession.AuthorizedPersonAlias.Person); authCheckResponse.IsAuthenciated = true; // Link personal device var tvDeviceTypeValueId = DefinedValueCache.Get(SystemGuid.DefinedValue.PERSONAL_DEVICE_TYPE_TV).Id; var personalDeviceService = new PersonalDeviceService(rockContext); var personalDevice = personalDeviceService.Queryable() .Where(a => a.DeviceUniqueIdentifier == deviceData.DeviceIdentifier && a.PersonalDeviceTypeValueId == tvDeviceTypeValueId && a.SiteId == siteId) .FirstOrDefault(); if (personalDevice != null) { personalDevice.PersonAliasId = validatedSession.AuthorizedPersonAliasId; } } else { authCheckResponse.IsAuthenciated = false; } rockContext.SaveChanges(); // Return response.Content = new StringContent(authCheckResponse.ToJson(), System.Text.Encoding.UTF8, "application/json"); response.StatusCode = HttpStatusCode.OK; return(response); }
public IHttpActionResult PostInteractions([FromBody] List <TvInteractionSession> sessions, Guid?personalDeviceGuid = null) { var person = GetPerson(); var ipAddress = System.Web.HttpContext.Current?.Request?.UserHostAddress; using (var rockContext = new 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(Rock.SystemGuid.DefinedValue.INTERACTIONCHANNELTYPE_WEBSITE); var pageEntityTypeId = EntityTypeCache.Get(typeof(Rock.Model.Page)).Id; // Check to see if we have a site and the API key is valid. if (TvHelper.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(TvInteraction 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 tvSession in sessions) { var interactionGuids = tvSession.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 tvInteraction in tvSession.Interactions.Where(i => !existingInteractionGuids.Contains(i.Guid))) { string cacheKey = GetComponentCacheKey(tvInteraction); if (!interactionComponentLookup.ContainsKey(cacheKey)) { // Shouldn't happen, but just in case. continue; } var interactionComponentId = interactionComponentLookup[cacheKey]; // // Add the interaction // var interaction = interactionService.CreateInteraction(interactionComponentId, tvInteraction.EntityId, tvInteraction.Operation, tvInteraction.Summary, tvInteraction.Data, person?.PrimaryAliasId, RockDateTime.ConvertLocalDateTimeToRockDateTime(tvInteraction.DateTime.LocalDateTime), tvSession.Application, tvSession.OperatingSystem, tvSession.ClientType, null, ipAddress, tvSession.Guid); interaction.Guid = tvInteraction.Guid; interaction.PersonalDeviceId = personalDeviceId; interaction.RelatedEntityTypeId = tvInteraction.RelatedEntityTypeId; interaction.RelatedEntityId = tvInteraction.RelatedEntityId; interaction.ChannelCustom1 = tvInteraction.ChannelCustom1; interaction.ChannelCustom2 = tvInteraction.ChannelCustom2; interaction.ChannelCustomIndexed1 = tvInteraction.ChannelCustomIndexed1; interaction.InteractionTimeToServe = tvInteraction.InteractionTimeToServe; interactionService.Add(interaction); } } rockContext.SaveChanges(); }); } return(Ok()); }