public void Execute()
        {
            if (PageId.HasValue || !string.IsNullOrWhiteSpace(ComponentName))
            {
                using (var rockContext = new RockContext())
                {
                    int channelMediumTypeValueId  = DefinedValueCache.Get(AvalancheUtilities.AppMediumValue.AsGuid()).Id;
                    var interactionChannelService = new InteractionChannelService(rockContext);
                    var interactionService        = new InteractionService(rockContext);
                    var interactionChannel        = interactionChannelService.Queryable()
                                                    .Where(a =>
                                                           a.ChannelTypeMediumValueId == channelMediumTypeValueId &&
                                                           a.ChannelEntityId == this.SiteId)
                                                    .FirstOrDefault();
                    if (interactionChannel == null)
                    {
                        interactionChannel      = new InteractionChannel();
                        interactionChannel.Name = SiteCache.Get(SiteId ?? 1).Name;
                        interactionChannel.ChannelTypeMediumValueId = channelMediumTypeValueId;
                        interactionChannel.ChannelEntityId          = this.SiteId;
                        interactionChannel.ComponentEntityTypeId    = EntityTypeCache.Get <Rock.Model.Page>().Id;
                        interactionChannelService.Add(interactionChannel);
                        rockContext.SaveChanges();
                    }

                    InteractionComponent interactionComponent = null;
                    var interactionComponentService           = new InteractionComponentService(rockContext);

                    if (PageId.HasValue)
                    {
                        interactionComponent = interactionComponentService.GetComponentByEntityId(interactionChannel.Id, PageId.Value, PageTitle);
                    }
                    else
                    {
                        interactionComponent = interactionComponentService.GetComponentByComponentName(interactionChannel.Id, ComponentName);
                    }
                    rockContext.SaveChanges();

                    // Add the interaction
                    if (interactionComponent != null)
                    {
                        var deviceId = Regex.Match(UserAgent, "(?<=-).+(?=\\))").Value.Trim();
                        if (deviceId.Length > 20)
                        {
                            deviceId = deviceId.Substring(0, 20);
                        }
                        var deviceApplication = Regex.Match(UserAgent, "^[\\S]{0,}").Value.Trim() + " " + deviceId;
                        var clientOs          = Regex.Match(UserAgent, "(?<=;).+(?=-)").Value.Trim();
                        var clientType        = Regex.Match(UserAgent, "(?<=\\().+(?=;)").Value.Trim();

                        var deviceType = interactionService.GetInteractionDeviceType(deviceApplication, clientOs, clientType, UserAgent);
                        var interactionSessionService = new InteractionSessionService(rockContext);
                        var interactionSession        = interactionSessionService.Queryable().Where(s => s.IpAddress == IPAddress && s.DeviceTypeId == deviceType.Id).FirstOrDefault();

                        if (interactionSession == null)
                        {
                            interactionSession = new InteractionSession()
                            {
                                DeviceTypeId = deviceType.Id,
                                IpAddress    = TrimString(IPAddress, 25)
                            };
                            interactionSessionService.Add(interactionSession);
                            rockContext.SaveChanges();
                        }

                        Operation          = TrimString(Operation, 25);
                        InteractionSummary = TrimString(InteractionSummary, 500);
                        clientType         = TrimString(clientType, 25);
                        deviceApplication  = TrimString(deviceApplication, 100);
                        clientOs           = TrimString(clientOs, 100);

                        var interaction = new InteractionService(rockContext).AddInteraction(interactionComponent.Id, null, Operation, InteractionData, PersonAliasId, DateViewed,
                                                                                             deviceApplication, clientOs, clientType, UserAgent, IPAddress, interactionSession.Guid);

                        interaction.InteractionSummary = InteractionSummary;

                        PersonalDevice personalDevice = AvalancheUtilities.GetPersonalDevice(deviceId, PersonAliasId, rockContext);
                        if (personalDevice != null)
                        {
                            interaction.PersonalDeviceId = personalDevice.Id;
                        }

                        rockContext.SaveChanges();
                    }
                }
            }
        }
Example #2
0
        /// <summary>
        /// Execute method to write transaction to the database.
        /// </summary>
        public void Execute()
        {
            using ( var rockContext = new RockContext() )
            {

                var userAgent = (this.UserAgent ?? string.Empty).Trim();
                if ( userAgent.Length > 450 )
                {
                    userAgent = userAgent.Substring( 0, 450 ); // trim super long useragents to fit in pageViewUserAgent.UserAgent
                }

                // get user agent info
                var clientType = PageViewUserAgent.GetClientType( userAgent );

                // don't log visits from crawlers
                if ( clientType != "Crawler" )
                {
                    InteractionChannelService interactionChannelService = new InteractionChannelService( rockContext );
                    InteractionComponentService interactionComponentService = new InteractionComponentService( rockContext );
                    InteractionDeviceTypeService interactionDeviceTypeService = new InteractionDeviceTypeService( rockContext );
                    InteractionSessionService interactionSessionService = new InteractionSessionService( rockContext );
                    InteractionService interactionService = new InteractionService( rockContext );

                    ClientInfo client = uaParser.Parse( userAgent );
                    var clientOs = client.OS.ToString();
                    var clientBrowser = client.UserAgent.ToString();

                    // lookup the interactionDeviceType, and create it if it doesn't exist
                    var interactionDeviceType = interactionDeviceTypeService.Queryable().Where( a => a.Application == clientBrowser
                                                && a.OperatingSystem == clientOs && a.ClientType == clientType ).FirstOrDefault();

                    if ( interactionDeviceType == null )
                    {
                        interactionDeviceType = new InteractionDeviceType();
                        interactionDeviceType.DeviceTypeData = userAgent;
                        interactionDeviceType.ClientType = clientType;
                        interactionDeviceType.OperatingSystem = clientOs;
                        interactionDeviceType.Application = clientBrowser;
                        interactionDeviceType.Name = string.Format( "{0} - {1}", clientOs, clientBrowser );
                        interactionDeviceTypeService.Add( interactionDeviceType );
                        rockContext.SaveChanges();
                    }

                    // lookup interactionSession, and create it if it doesn't exist
                    Guid sessionId = this.SessionId.AsGuid();
                    int? interactionSessionId = interactionSessionService.Queryable()
                                                    .Where(
                                                        a => a.DeviceTypeId == interactionDeviceType.Id
                                                        && a.Guid == sessionId )
                                                    .Select( a => (int?)a.Id )
                                                    .FirstOrDefault();

                    if ( !interactionSessionId.HasValue )
                    {
                        var interactionSession = new InteractionSession();
                        interactionSession.DeviceTypeId = interactionDeviceType.Id;
                        interactionSession.IpAddress = this.IPAddress;
                        interactionSession.Guid = sessionId;
                        interactionSessionService.Add( interactionSession );
                        rockContext.SaveChanges();
                        interactionSessionId = interactionSession.Id;
                    }

                    int componentEntityTypeId = EntityTypeCache.Read<Rock.Model.Page>().Id;
                    string siteName = SiteCache.Read( SiteId ?? 1 ).Name;

                    // lookup the interaction channel, and create it if it doesn't exist
                    int channelMediumTypeValueId = DefinedValueCache.Read( SystemGuid.DefinedValue.INTERACTIONCHANNELTYPE_WEBSITE.AsGuid() ).Id;

                    // check that the site exists as a channel
                    var interactionChannel = interactionChannelService.Queryable()
                                                        .Where( a =>
                                                            a.ChannelTypeMediumValueId == channelMediumTypeValueId
                                                            && a.ChannelEntityId == this.SiteId )
                                                        .FirstOrDefault();
                    if ( interactionChannel == null )
                    {
                        interactionChannel = new InteractionChannel();
                        interactionChannel.Name = siteName;
                        interactionChannel.ChannelTypeMediumValueId = channelMediumTypeValueId;
                        interactionChannel.ChannelEntityId = this.SiteId;
                        interactionChannel.ComponentEntityTypeId = componentEntityTypeId;
                        interactionChannelService.Add( interactionChannel );
                        rockContext.SaveChanges();
                    }

                    // check that the page exists as a component
                    var interactionComponent = interactionComponentService.Queryable()
                                                        .Where( a =>
                                                            a.EntityId == PageId
                                                            && a.ChannelId == interactionChannel.Id )
                                                        .FirstOrDefault();
                    if ( interactionComponent == null )
                    {
                        interactionComponent = new InteractionComponent();
                        interactionComponent.Name = PageTitle;
                        interactionComponent.EntityId = PageId;
                        interactionComponent.ChannelId = interactionChannel.Id;
                        interactionComponentService.Add( interactionComponent );
                        rockContext.SaveChanges();
                    }

                    // add the interaction
                    Interaction interaction = new Interaction();
                    interactionService.Add( interaction );

                    // obfuscate rock magic token
                    Regex rgx = new Regex( @"rckipid=([^&]*)" );
                    string cleanUrl = rgx.Replace( this.Url, "rckipid=XXXXXXXXXXXXXXXXXXXXXXXXXXXX" );

                    interaction.InteractionData = cleanUrl;
                    interaction.Operation = "View";
                    interaction.PersonAliasId = this.PersonAliasId;
                    interaction.InteractionDateTime = this.DateViewed;
                    interaction.InteractionSessionId = interactionSessionId;
                    interaction.InteractionComponentId = interactionComponent.Id;
                    rockContext.SaveChanges();
                }
            }
        }
Example #3
0
        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());
        }
Example #4
0
        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());
        }