/// <summary>
        /// Initializes a new instance of the <see cref="ContentAccessConfiguration"/> class.
        /// </summary>
        /// <param name="siteSettingName">Site Setting Name</param>
        /// <param name="sourceEntityName">Source Entity Name</param>
        /// <param name="targetEntityName">Target Entity Name</param>
        /// <param name="targetFromAttribute">Target From Attribute</param>
        /// <param name="targetToAttribute">Target To Attribute</param>
        /// <param name="intersectEntityName">Intersect Entity Name</param>
        /// <param name="intersectFromAttribute">Intersect From Attribute</param>
        /// <param name="intersectToAttribute">Intersect To Attribute</param>
        public ContentAccessConfiguration(string siteSettingName, string sourceEntityName, string targetEntityName, string targetFromAttribute, string targetToAttribute, string intersectEntityName, string intersectFromAttribute, string intersectToAttribute)
        {
            var linkEntityAliasGenerator = LinkEntityAliasGenerator.CreateInstance();

            this.SiteSettingName        = siteSettingName;
            this.SourceEntityName       = sourceEntityName;
            this.TargetEntityName       = targetEntityName;
            this.TargetFromAttribute    = targetFromAttribute;
            this.TargetToAttribute      = targetToAttribute;
            this.TargetAlias            = linkEntityAliasGenerator.CreateUniqueAlias(targetEntityName);
            this.IntersectEntityName    = intersectEntityName;
            this.IntersectFromAttribute = intersectFromAttribute;
            this.IntersectToAttribute   = intersectToAttribute;
            this.IntersectAlias         = linkEntityAliasGenerator.CreateUniqueAlias(intersectEntityName);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Constructs a link-entity chain from the <paramref name="fetch"/>
        /// </summary>
        /// <param name="customerToProductRelationshipNamesCollection">Collection of relationships that map from Customer to Product</param>
        /// <param name="fetch">Fetch used to construct link chain</param>
        /// <param name="filter">Filter to inject conditions into</param>
        /// <param name="contact">Contact EntityReference</param>
        /// <param name="account">Account EntityReference</param>
        /// <param name="owningCustomerType">Owning Customer Type</param>
        /// <param name="linkEntityAliasGenerator">Single instance to maintain alias postfix incrementation</param>
        /// <returns>Root link of the constructed chain</returns>
        private Link BuildLinksAndFilterChain(string[] customerToProductRelationshipNamesCollection,
                                              Fetch fetch, Filter filter, EntityReference contact, EntityReference account,
                                              OwningCustomerType owningCustomerType, LinkEntityAliasGenerator linkEntityAliasGenerator)
        {
            var rootLink    = new Link();
            var linkDetails = this.GetLinkDetails(customerToProductRelationshipNamesCollection, owningCustomerType);

            foreach (var linkDetail in linkDetails)
            {
                var innermostLink = GetInnermostLink(rootLink);

                var currentLinkDetailConnectsToAccountOrContact = (contact != null && (linkDetail.Entity1Name == "contact" || linkDetail.Entity2Name == "contact")) ||
                                                                  (account != null && (linkDetail.Entity1Name == "account" || linkDetail.Entity2Name == "account"));
                this.BuildLinksAndFilter(this.Portal.ServiceContext, linkDetail, fetch, innermostLink, filter, contact, account, currentLinkDetailConnectsToAccountOrContact, linkEntityAliasGenerator);
            }

            return(rootLink);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Modify a fetch and add necessary link entity elements and filter conditions to satisfy record level security trimming based on the relationship definitions.
        /// </summary>
        /// <param name="serviceContext"><see cref="OrganizationServiceContext"/> to use</param>
        /// <param name="linkDetails"><see cref="ContentAccessProvider.LinkDetails"/> to use</param>
        /// <param name="fetch">Fetch to modify</param>
        /// <param name="link">Link to construct</param>
        /// <param name="filter">Filter to construct</param>
        /// <param name="contact">Associated Contact</param>
        /// <param name="account">Associated Account</param>
        /// <param name="addCondition">Construct Account/Contact relationship filter</param>
        /// <param name="linkEntityAliasGenerator">LinkEntityAliasGenerator to track and create Aliases</param>
        private void BuildLinksAndFilter(OrganizationServiceContext serviceContext, LinkDetails linkDetails, Fetch fetch, Link link, Filter filter, EntityReference contact, EntityReference account, bool addCondition, LinkEntityAliasGenerator linkEntityAliasGenerator)
        {
            var relationshipMetadata = this.BuildRelationshipMetadata(serviceContext, linkDetails);

            ProductAccessProvider.BuildLinksAndFilter(serviceContext, relationshipMetadata, linkDetails, fetch, link, filter, contact, account, addCondition, linkEntityAliasGenerator);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Modify a fetch and add necessary link entity elements and filter conditions to satisfy record level security trimming based on the relationship definitions.
        /// </summary>
        /// <param name="serviceContext"><see cref="OrganizationServiceContext"/> to use</param>
        /// <param name="relationshipMetadata">Relationship metadata that defines relationship attributes</param>
        /// <param name="linkDetails"><see cref="ContentAccessProvider.LinkDetails"/> to use</param>
        /// <param name="fetch">Fetch to modify</param>
        /// <param name="link">Link to construct</param>
        /// <param name="filter">Filter to construct</param>
        /// <param name="contact">Associated Contact</param>
        /// <param name="account">Associated Account</param>
        /// <param name="addCondition">Construct Account/Contact relationship filter</param>
        /// <param name="linkEntityAliasGenerator">LinkEntityAliasGenerator to track and create Aliases</param>
        private static void BuildLinksAndFilter(OrganizationServiceContext serviceContext, ProductAccessProvider.RelationshipMetadata relationshipMetadata, LinkDetails linkDetails, Fetch fetch, Link link, Filter filter, EntityReference contact, EntityReference account, bool addCondition, LinkEntityAliasGenerator linkEntityAliasGenerator)
        {
            var  alias   = linkEntityAliasGenerator.CreateUniqueAlias(relationshipMetadata.Entity2LogicalName);
            Link newLink = null;


            if (relationshipMetadata.RelationshipType == ProductAccessProvider.RelationshipType.ManyToManyRelationship)
            {
                var    intersectLinkEntityName = relationshipMetadata.IntersectEntityName;
                string linkTargetFromAttribute;
                string linkTargetToAttribute;
                string linkIntersectFromAttribute;
                string linkIntersectToAttribute;
                if (relationshipMetadata.Entity1LogicalName == relationshipMetadata.Entity2LogicalName)
                {
                    linkIntersectFromAttribute = relationshipMetadata.Entity2IntersectAttribute;
                    linkIntersectToAttribute   = relationshipMetadata.Entity1PrimaryIdAttribute;
                    linkTargetFromAttribute    = relationshipMetadata.Entity1PrimaryIdAttribute;
                    linkTargetToAttribute      = relationshipMetadata.Entity1IntersectAttribute;
                }
                else
                {
                    linkIntersectFromAttribute   =
                        linkIntersectToAttribute = relationshipMetadata.Entity1LogicalName == linkDetails.Entity1Name
                            ? relationshipMetadata.Entity1IntersectAttribute
                            : relationshipMetadata.Entity2IntersectAttribute;
                    linkTargetFromAttribute   =
                        linkTargetToAttribute = relationshipMetadata.Entity2LogicalName == linkDetails.Entity2Name
                            ? relationshipMetadata.Entity2IntersectAttribute
                            : relationshipMetadata.Entity1IntersectAttribute;
                }

                newLink = new Link
                {
                    Name          = intersectLinkEntityName,
                    FromAttribute = linkIntersectFromAttribute,
                    ToAttribute   = linkIntersectToAttribute,
                    Intersect     = true,
                    Visible       = false,
                    Type          = JoinOperator.LeftOuter,
                    Links         = new List <Link>
                    {
                        new Link
                        {
                            Name          = relationshipMetadata.Entity2LogicalName,
                            FromAttribute = linkTargetFromAttribute,
                            ToAttribute   = linkTargetToAttribute,
                            Alias         = alias,
                            Type          = JoinOperator.LeftOuter
                        }
                    }
                };
            }
            else if (relationshipMetadata.RelationshipType == ProductAccessProvider.RelationshipType.ManyToOneRelationship)
            {
                var linkFromAttribute = relationshipMetadata.ReferencedEntity == relationshipMetadata.Entity2LogicalName
                    ? relationshipMetadata.ReferencedAttribute
                    : relationshipMetadata.ReferencingAttribute;

                var linkToAttribute = relationshipMetadata.ReferencedEntity == relationshipMetadata.Entity2LogicalName
                    ? relationshipMetadata.ReferencingAttribute
                    : relationshipMetadata.ReferencedAttribute;

                newLink = new Link
                {
                    Name          = relationshipMetadata.Entity2LogicalName,
                    FromAttribute = linkFromAttribute,
                    ToAttribute   = linkToAttribute,
                    Type          = JoinOperator.LeftOuter,
                    Alias         = alias
                };
            }
            else if (relationshipMetadata.RelationshipType == ProductAccessProvider.RelationshipType.OneToManyRelationship)
            {
                var linkFromAttribute = relationshipMetadata.ReferencedEntity == relationshipMetadata.Entity2LogicalName
                    ? relationshipMetadata.ReferencedAttribute
                    : relationshipMetadata.ReferencingAttribute;

                var linkToAttribute = relationshipMetadata.ReferencedEntity == relationshipMetadata.Entity2LogicalName
                    ? relationshipMetadata.ReferencingAttribute
                    : relationshipMetadata.ReferencedAttribute;

                newLink = new Link
                {
                    Name          = relationshipMetadata.Entity2LogicalName,
                    FromAttribute = linkFromAttribute,
                    ToAttribute   = linkToAttribute,
                    Type          = JoinOperator.LeftOuter,
                    Alias         = alias
                };
            }
            else
            {
                throw new ApplicationException(string.Format("Retrieve relationship request failed for relationship name {0}", linkDetails.RelationshipName));
            }

            ContentAccessProvider.AddLink(link, newLink);


            if (addCondition) // Only add the condition if we are at the end of the chain
            {
                var condition = new Condition {
                    Attribute = relationshipMetadata.Entity2PrimaryIdAttribute
                };

                if (linkDetails.Scope.HasValue && linkDetails.Scope.Value == OwningCustomerType.Contact)
                {
                    condition.EntityName = alias;
                    condition.Operator   = ConditionOperator.Equal;
                    condition.Value      = contact.Id;
                }
                else if (linkDetails.Scope.HasValue && linkDetails.Scope.Value == OwningCustomerType.Account)
                {
                    condition.EntityName = alias;
                    condition.Operator   = ConditionOperator.Equal;
                    condition.Value      = account.Id;
                }
                else
                {
                    condition.EntityName = alias;
                    condition.Operator   = ConditionOperator.NotNull;
                }

                filter.Conditions.Add(condition);
            }

            fetch.Distinct = true;
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Retrieves the list of Products available to the current user
        /// </summary>
        /// <returns>Product entity collection</returns>
        public List <Guid> GetProducts()
        {
            // If anonymous user, return nothing
            if (this.CurrentUserEntityReference == null)
            {
                return(Enumerable.Empty <Guid>().ToList());
            }

            var productFetch = new Fetch
            {
                Distinct = true,
                Entity   = new FetchEntity
                {
                    Name       = "product",
                    Attributes = new List <FetchAttribute>
                    {
                        new FetchAttribute("productid")
                    },
                    Filters = new List <Filter>()
                }
            };

            var associatedToAccountOrContactFilter = new Filter
            {
                Type       = LogicalOperator.Or,
                Conditions = new List <Condition>(),
                Filters    = new List <Filter>()
            };

            // Get alias generator instance to maintain alias names consistency
            // via postfix incrementation
            var linkEntityAliasGenerator = LinkEntityAliasGenerator.CreateInstance();

            // Retrieve Contact to Product relationships and build Entity Permission links
            var contactToProductRelationshipNamesCollection =
                this.GetDelimitedSiteSettingValueCollection(ContactToProductRelationshipNames, ContactToProductFallbackRelationshipName);
            var contactLink = this.BuildLinksAndFilterChain(
                contactToProductRelationshipNamesCollection, productFetch, associatedToAccountOrContactFilter,
                this.CurrentUserEntityReference, null, OwningCustomerType.Contact, linkEntityAliasGenerator);

            productFetch.AddLink(contactLink);

            if (this.ParentCustomerEntityReference != null && this.ParentCustomerEntityReference.LogicalName == "contact")
            {
                // Retrieve parent Contact to Product relationships and build Entity Permission links
                var parentContactLink = this.BuildLinksAndFilterChain(
                    contactToProductRelationshipNamesCollection, productFetch, associatedToAccountOrContactFilter,
                    this.ParentCustomerEntityReference, null, OwningCustomerType.Contact, linkEntityAliasGenerator);
                productFetch.AddLink(parentContactLink);
            }
            else if (this.ParentCustomerEntityReference != null && this.ParentCustomerEntityReference.LogicalName == "account")
            {
                // Retrieve Account to Product relationships and build Entity Permission links
                var accountToProductRelationshipNamesCollection =
                    this.GetDelimitedSiteSettingValueCollection(AccountToProductRelationshipNames, AccountToProductFallbackRelationshipName);
                var accountLink = this.BuildLinksAndFilterChain(
                    accountToProductRelationshipNamesCollection, productFetch, associatedToAccountOrContactFilter,
                    null, this.ParentCustomerEntityReference, OwningCustomerType.Account, linkEntityAliasGenerator);
                productFetch.AddLink(accountLink);
            }

            var accountOrContactNotNullFilter = new Filter
            {
                Type       = LogicalOperator.Or,
                Conditions =
                    associatedToAccountOrContactFilter.Conditions.Select(
                        condition =>
                        new Condition
                {
                    EntityName = condition.EntityName,
                    Attribute  = condition.Attribute,
                    Operator   = ConditionOperator.NotNull
                }).ToList()
            };

            // This is the AND Filter that will ensure state is Active and the Product is joined to either Contact or Account
            productFetch.AddFilter(new Filter
            {
                Type       = LogicalOperator.And,
                Conditions = new List <Condition>
                {
                    new Condition("statecode", ConditionOperator.Equal, 0)
                },
                Filters = new List <Filter>
                {
                    accountOrContactNotNullFilter,
                    associatedToAccountOrContactFilter,
                }
            });

            var productsCollection = productFetch.Execute(this.Portal.ServiceContext as IOrganizationService);

            return(productsCollection.Entities.Select(x => x.Id).ToList());
        }
        /// <summary>
        /// Add the necessary filter conditions to filter related records
        /// </summary>
        /// <param name="serviceContext"><see cref="OrganizationServiceContext"/></param>
        /// <param name="fetch"><see cref="Fetch"/></param>
        /// <param name="id">Id of the record to filter related</param>
        protected void AddFiltersToFetch(OrganizationServiceContext serviceContext, Fetch fetch, string id)
        {
            if (string.IsNullOrWhiteSpace(Metadata.ViewRelationshipName))
            {
                return;
            }

            var linkEntityAliasGenerator = LinkEntityAliasGenerator.CreateInstance(fetch);
            var metadataManyToMany       = EntityMetadata.ManyToManyRelationships.FirstOrDefault(r => r.SchemaName == Metadata.ViewRelationshipName);
            var relationshipManyToOne    = EntityMetadata.ManyToOneRelationships.FirstOrDefault(r => r.SchemaName == Metadata.ViewRelationshipName);
            var relationshipOneToMany    = EntityMetadata.OneToManyRelationships.FirstOrDefault(r => r.SchemaName == Metadata.ViewRelationshipName);

            if (metadataManyToMany != null)
            {
                var    linkIntersectName = metadataManyToMany.IntersectEntityName;
                string linkTargetFromAttribute;
                string linkTargetToAttribute;
                string linkIntersectFromAttribute;
                string linkIntersectToAttribute;
                if (metadataManyToMany.Entity1LogicalName == metadataManyToMany.Entity2LogicalName)
                {
                    linkIntersectFromAttribute = metadataManyToMany.Entity2IntersectAttribute;
                    linkIntersectToAttribute   = EntityMetadata.PrimaryIdAttribute;
                    linkTargetFromAttribute    = EntityMetadata.PrimaryIdAttribute;
                    linkTargetToAttribute      = metadataManyToMany.Entity1IntersectAttribute;
                }
                else
                {
                    linkTargetFromAttribute = linkTargetToAttribute = metadataManyToMany.Entity1LogicalName == Metadata.TargetEntityName
                                                ? metadataManyToMany.Entity1IntersectAttribute
                                                : metadataManyToMany.Entity2IntersectAttribute;
                    linkIntersectFromAttribute = linkIntersectToAttribute = metadataManyToMany.Entity1LogicalName == Metadata.ViewTargetEntityType
                                                ? metadataManyToMany.Entity1IntersectAttribute
                                                : metadataManyToMany.Entity2IntersectAttribute;
                }

                var link = new Link
                {
                    Name          = linkIntersectName,
                    FromAttribute = linkIntersectFromAttribute,
                    ToAttribute   = linkIntersectToAttribute,
                    Intersect     = true,
                    Visible       = false,
                    Links         = new List <Link>
                    {
                        new Link
                        {
                            Name          = Metadata.TargetEntityName,
                            FromAttribute = linkTargetFromAttribute,
                            ToAttribute   = linkTargetToAttribute,
                            Alias         = linkEntityAliasGenerator.CreateUniqueAlias(Metadata.TargetEntityName),
                            Filters       = new List <Filter>
                            {
                                new Filter
                                {
                                    Type       = LogicalOperator.And,
                                    Conditions = new List <Condition>
                                    {
                                        new Condition
                                        {
                                            Attribute = linkTargetFromAttribute,
                                            Operator  = ConditionOperator.Equal,
                                            Value     = id
                                        }
                                    }
                                }
                            }
                        }
                    }
                };

                if (fetch.Entity.Links == null)
                {
                    fetch.Entity.Links = new List <Link> {
                        link
                    };
                }
                else
                {
                    fetch.Entity.Links.Add(link);
                }
            }
            else if (relationshipManyToOne != null)
            {
                var link = new Link
                {
                    Name          = Metadata.TargetEntityName,
                    FromAttribute = relationshipManyToOne.ReferencedAttribute,
                    ToAttribute   = relationshipManyToOne.ReferencingAttribute,
                    Alias         = linkEntityAliasGenerator.CreateUniqueAlias(Metadata.TargetEntityName),
                    Filters       = new List <Filter>
                    {
                        new Filter
                        {
                            Type       = LogicalOperator.And,
                            Conditions = new List <Condition>
                            {
                                new Condition
                                {
                                    Attribute = relationshipManyToOne.ReferencedAttribute,
                                    Operator  = ConditionOperator.Equal,
                                    Value     = id
                                }
                            }
                        }
                    }
                };

                if (fetch.Entity.Links == null)
                {
                    fetch.Entity.Links = new List <Link> {
                        link
                    };
                }
                else
                {
                    fetch.Entity.Links.Add(link);
                }
            }
            else if (relationshipOneToMany != null)
            {
                var attribute = relationshipOneToMany.ReferencedEntity == Metadata.TargetEntityName
                                        ? relationshipOneToMany.ReferencedAttribute
                                        : relationshipOneToMany.ReferencingAttribute;

                var filter = new Filter
                {
                    Type       = LogicalOperator.And,
                    Conditions = new List <Condition>
                    {
                        new Condition
                        {
                            Attribute = attribute,
                            Operator  = ConditionOperator.Equal,
                            Value     = id
                        }
                    }
                };

                AddFilterToFetch(fetch, filter);
            }
            else
            {
                throw new ApplicationException(string.Format("RetrieveRelationshipRequest failed for view relationship name {0}", Metadata.ViewRelationshipName));
            }
        }