private bool TryCreateHandler(IPortalContext portal, ContentMap map, out IHttpHandler handler)
        {
            switch (portal.Entity.LogicalName)
            {
            case "adx_webfile":
                WebFileNode webfile;
                if (map.TryGetValue(portal.Entity, out webfile))
                {
                    if (CloudBlobRedirectHandler.TryGetCloudBlobHandler(portal.Entity, out handler))
                    {
                        return(true);
                    }

                    // retrieve the most recently created annotation
                    var note = webfile.Annotations.OrderByDescending(a => a.CreatedOn).FirstOrDefault();
                    return(TryCreateHandler(note, webfile, portal, out handler));
                }
                break;

            case "annotation":
                AnnotationNode annotation;
                if (map.TryGetValue(portal.Entity, out annotation))
                {
                    return(TryCreateHandler(annotation, null, portal, out handler));
                }
                break;
            }

            return(base.TryCreateHandler(portal, out handler));
        }
        protected override bool TryAssert(OrganizationServiceContext context, Entity entity, CrmEntityRight right, CrmEntityCacheDependencyTrace dependencies, ContentMap map)
        {
            var entityName = entity.LogicalName;

            this.AddDependencies(
                dependencies,
                entity,
                new[] { "adx_webrole", "adx_webrole_contact", "adx_webrole_account", "adx_websiteaccess" });

            if (entityName == "adx_weblink")
            {
                // Change permission only comes through adx_manageweblinksets on the website.
                if (right == CrmEntityRight.Change)
                {
                    return(TryAssertRightProperty(context, "adx_manageweblinksets", dependencies));
                }

                WebLinkNode link;

                if (map.TryGetValue(entity, out link))
                {
                    dependencies.IsCacheable = false;

                    if (link.DisablePageValidation.GetValueOrDefault())
                    {
                        return(true);
                    }

                    return(link.WebPage == null || link.WebPage.IsReference || (_webPageAccessControlSecurityProvider != null && _webPageAccessControlSecurityProvider.TryAssert(link.WebPage, right, false)));
                }
            }

            WebsiteNode site;

            if (!map.TryGetValue(_website, out site))
            {
                return(false);
            }

            if (entityName == "adx_contentsnippet")
            {
                return(right == CrmEntityRight.Read || TryAssertRightProperty(site, rule => rule.ManageContentSnippets));
            }

            if (entityName == "adx_weblinkset")
            {
                return(right == CrmEntityRight.Read || TryAssertRightProperty(site, rule => rule.ManageWebLinkSets));
            }

            if (entityName == "adx_sitemarker")
            {
                return(right == CrmEntityRight.Read || TryAssertRightProperty(site, rule => rule.ManageSiteMarkers));
            }

            return(false);
        }
        /// <summary>
        /// Select all idea forum web roles.
        /// </summary>
        /// <param name="entityId">
        /// The entity id.
        /// </param>
        /// <param name="contentMap">
        /// The content map.
        /// </param>
        /// <returns>
        /// The <see cref="IEnumerable"/> of web roles associated to the Idea Forum.
        /// </returns>
        private static IEnumerable <string> SelectAllIdeaForumWebRoles(Guid entityId, ContentMap contentMap)
        {
            EntityNode entity;

            // Get the idea forum from the content map
            if (!contentMap.TryGetValue(new EntityReference("adx_ideaforum", entityId), out entity))
            {
                return(Enumerable.Empty <string>());
            }

            var idea = entity as IdeaForumNode;

            if (idea == null)
            {
                return(Enumerable.Empty <string>());
            }

            // In IdeaSecurityProvider.cs the idea is readable if the user is in the given roles or if there is no roles
            // given then all can read. Thus if WebRolesRead has none in there we need to add all the roles.
            if (idea.WebRolesRead.Any())
            {
                // But if there are some Read rules then add them as well as the write rules as if they have any of them then they
                // Should be allowed to read it.
                return(idea.WebRolesRead.Select(w => w.Name).Concat(idea.WebRolesWrite.Select(w => w.Name)));
            }

            // If it doesn't have any specific read roles then add all zero guid as a sign that everyone should have access.
            return(new[] { AllowAccessDefaultValue });
        }
        /// <summary>
        /// Selects all guids of descendant web pages for the given web page.
        /// </summary>
        /// <param name="entityId">
        /// The webpage Id.
        /// </param>
        /// <param name="contentMap">
        /// The content map.
        /// </param>
        /// <param name="predicates">
        /// <see cref="IEnumerable"/> of predicates to determine whether a web page should be included in the results. Executed in order with short circuiting.
        /// </param>
        /// <returns>
        /// The <see cref="IEnumerable"/> of the web page GUIDs for descendant web pages.
        /// </returns>
        private static IEnumerable <Guid> SelectAllDescendantWebpagesWithPredicates(Guid entityId, ContentMap contentMap, IEnumerable <Predicate <WebPageNode> > predicates)
        {
            EntityNode entity;

            if (!contentMap.TryGetValue(new EntityReference("adx_webpage", entityId), out entity))
            {
                return(Enumerable.Empty <Guid>());
            }

            var rootWebpage = entity as WebPageNode;

            if (rootWebpage == null)
            {
                return(Enumerable.Empty <Guid>());
            }

            // if it's a content page, we want to start at it's root page so we can navigate down the web page hierarchy
            if (rootWebpage.IsRoot == false)
            {
                if (rootWebpage.RootWebPage == null)
                {
                    // just return this web page, can't reach any others
                    return(new List <Guid>()
                    {
                        rootWebpage.Id
                    });
                }

                rootWebpage = rootWebpage.RootWebPage;
            }

            var unprocessedNodes = new Queue <WebPageNode>();
            var webPageGuids     = new List <Guid>();

            unprocessedNodes.Enqueue(rootWebpage);
            while (unprocessedNodes.Count > 0)
            {
                WebPageNode currWebPage = unprocessedNodes.Dequeue();

                foreach (var childWebPage in currWebPage.WebPages)
                {
                    unprocessedNodes.Enqueue(childWebPage);
                }

                if (currWebPage.LanguageContentPages != null)
                {
                    foreach (var contentPage in currWebPage.LanguageContentPages)
                    {
                        unprocessedNodes.Enqueue(contentPage);
                    }
                }

                if (predicates.All(predicate => predicate(currWebPage)))
                {
                    webPageGuids.Add(currWebPage.Id);
                }
            }

            return(webPageGuids);
        }
Example #5
0
        private bool TryAssertIdea(OrganizationServiceContext serviceContext, Entity ideaEntity, CrmEntityRight right, CrmEntityCacheDependencyTrace dependencies, ContentMap map)
        {
            var ideaForumReference = ideaEntity.GetAttributeValue <EntityReference>("adx_ideaforumid");

            IdeaForumNode ideaForumNode;

            if (!map.TryGetValue(ideaForumReference, out ideaForumNode))
            {
                return(false);
            }
            var ideaForum = ideaForumNode.AttachTo(serviceContext);

            if (ideaForum == null)
            {
                return(false);
            }

            var approved = ideaEntity.GetAttributeValue <bool?>("adx_approved").GetValueOrDefault(false);

            // If the right being asserted is Read, and the idea is approved, assert whether the idea forum is readable.
            if (right == CrmEntityRight.Read && approved)
            {
                return(this.TryAssert(serviceContext, ideaForum, right, dependencies, map));
            }

            return(this.TryAssert(serviceContext, ideaForum, CrmEntityRight.Change, dependencies, map));
        }
        private ApplicationPath GetApplicationPath(ContentMap map, Entity entity)
        {
            EntityNode node;

            if (map.TryGetValue(entity, out node))
            {
                return(GetApplicationPath(map, node));
            }

            return(null);
        }
        private EntityReference GetExistingParent(EntityReference child, IDataAdapterDependencies dependencies, ContentMap map)
        {
            if (child.LogicalName == "adx_webpage")
            {
                WebPageNode webPage;

                if (map.TryGetValue(child, out webPage))
                {
                    var parent = webPage.Parent;

                    return(parent == null ? null : parent.ToEntityReference());
                }
            }

            if (child.LogicalName == "adx_webfile")
            {
                WebFileNode webFile;

                if (map.TryGetValue(child, out webFile))
                {
                    var parent = webFile.Parent;

                    return(parent == null ? null : parent.ToEntityReference());
                }
            }

            if (child.LogicalName == "adx_shortcut")
            {
                ShortcutNode shortcut;

                if (map.TryGetValue(child, out shortcut))
                {
                    var parent = shortcut.Parent;

                    return(parent == null ? null : parent.ToEntityReference());
                }
            }

            return(GetExistingParent(child, dependencies));
        }
        private bool TryAssertBlog(OrganizationServiceContext serviceContext, Entity entity, CrmEntityRight right, CrmEntityCacheDependencyTrace dependencies, ContentMap map)
        {
            var pageReference = entity.GetAttributeValue <EntityReference>("adx_parentpageid");

            if (pageReference == null)
            {
                return(false);
            }

            var parentPage = serviceContext.RetrieveSingle(
                "adx_webpage",
                new[] { "adx_name" },
                new Condition("adx_webpageid", ConditionOperator.Equal, pageReference.Id));

            if (right == CrmEntityRight.Read)
            {
                return(parentPage != null && this.WebPageSecurityProvider.TryAssert(serviceContext, parentPage, right, dependencies));
            }

            if (!Roles.Enabled)
            {
                ADXTrace.Instance.TraceError(TraceCategory.Application, "Roles are not enabled for this application. Denying Change.");

                return(false);
            }

            IEnumerable <Entity> authorRoles = new List <Entity>();
            EntityNode           blogNode;

            if (!map.TryGetValue(entity, out blogNode))
            {
                return(false);
            }

            if (blogNode is BlogNode)
            {
                authorRoles = ((BlogNode)blogNode).WebRoles.Select(wr => wr.ToEntity());
            }

            if (!authorRoles.Any())
            {
                return(false);
            }

            dependencies.AddEntityDependencies(authorRoles);

            var userRoles = this.GetUserRoles();

            return(authorRoles.Select(e => e.GetAttributeValue <string>("adx_name")).Intersect(userRoles, StringComparer.InvariantCulture).Any() ||
                   (parentPage != null && this.WebPageSecurityProvider.TryAssert(serviceContext, parentPage, right, dependencies)));
        }
        private WebPageNode GetRoot(ContentMap contentMap)
        {
            IDictionary <EntityReference, EntityNode> siteMarkers;

            if (!contentMap.TryGetValue("adx_sitemarker", out siteMarkers))
            {
                return(null);
            }

            var siteMarkerNode = siteMarkers.Values.Cast <SiteMarkerNode>()
                                 .FirstOrDefault(e => e.Website.Id == Website.Id && e.Name == "Home");

            if (siteMarkerNode == null || siteMarkerNode.WebPage == null)
            {
                return(null);
            }

            WebPageNode root;

            return(contentMap.TryGetValue(siteMarkerNode.WebPage, out root)
                                ? root
                                : null);
        }
        private static IEnumerable <string> GetRolesForGrouping(ContentMap map, Entity rule, EntityReference websiteReference)
        {
            IDictionary <EntityReference, EntityNode> intersectNodes;

            if (map.TryGetValue("adx_communityforumaccesspermission_webrole", out intersectNodes))
            {
                var ruleGroupingRoles =
                    intersectNodes.Values.Cast <ForumAccessPermissionsToWebRoleNode>()
                    .Where(i => i.ForumAccessPermission.Id == rule.Id && BelongsToWebsite(websiteReference, i.WebRole))
                    .Select(r => r.WebRole.Name);

                return(ruleGroupingRoles);
            }

            return(Enumerable.Empty <string>());
        }
        private ApplicationPath GetApplicationPath(ContentMap map, Entity entity, string partialUrlAttribute, string parentReferenceAttribute, bool trailingSlash = false, bool prependLangCode = false)
        {
            var partialUrl = entity.GetAttributeValue <string>(partialUrlAttribute);

            if (string.IsNullOrEmpty(partialUrl))
            {
                return(null);
            }

            var parentReference = entity.GetAttributeValue <EntityReference>(parentReferenceAttribute);

            if (parentReference == null)
            {
                return(null);
            }

            EntityNode parentNode;

            if (!map.TryGetValue(parentReference, out parentNode))
            {
                return(null);
            }

            var parentPath = GetApplicationPath(map, parentNode);

            if (parentPath == null || parentPath.PartialPath == null)
            {
                return(null);
            }

            partialUrl = trailingSlash && !partialUrl.EndsWith("/") ? partialUrl + "/" : partialUrl;

            var parentPartialPath = parentPath.PartialPath.EndsWith("/") ? parentPath.PartialPath : parentPath.PartialPath + "/";

            var resultAppPath = ApplicationPath.FromPartialPath(parentPartialPath + partialUrl);

            if (ContextLanguageInfo.DisplayLanguageCodeInUrl &&
                ContextLanguageInfo.IsCrmMultiLanguageEnabledInWebsite(PortalContext.Current.Website) &&
                prependLangCode)
            {
                resultAppPath = ContextLanguageInfo.PrependLanguageCode(resultAppPath);
            }

            return(resultAppPath);
        }
        protected virtual IEnumerable <Entity> GetRulesApplicableToForum(Entity forum, CrmEntityCacheDependencyTrace dependencies, ContentMap map)
        {
            forum.AssertEntityName("adx_communityforum");

            var rules = new List <Entity>();

            ForumNode currentForumNode;

            if (map.TryGetValue(forum, out currentForumNode))
            {
                var rulesForCurrentForum = currentForumNode.ForumAccessPermissions.Where(fr => fr.StateCode == 0);
                rules.AddRange(rulesForCurrentForum.Select(r => r.ToEntity()));
            }

            dependencies.AddEntityDependencies(rules);

            return(rules);
        }
        private static Task AddBulkAsync(ContentMap contentDirectory, ContentMap backupContentDirectory, ContentDirectorySnapshot <ContentFileInfo> hashInfoPairs)
        {
            return(hashInfoPairs.ParallelAddToConcurrentDictionaryAsync(
                       contentDirectory, hashInfoPair => hashInfoPair.Hash, hashInfoPair =>
            {
                var info = hashInfoPair.Payload;
                if (backupContentDirectory.TryGetValue(hashInfoPair.Hash, out var backupInfo))
                {
                    // Recover the last access time from the backup. This has the affect that
                    // content mentioned in the backup will be older than newly discovered content
                    return new ContentFileInfo(
                        info.FileSize,
                        backupInfo.LastAccessedFileTimeUtc,
                        info.ReplicaCount);
                }

                return info;
            }));
        }
        private bool TryGetWebsite(ContentMap map, out WebsiteNode site, out IContentMapEntityUrlProvider urlProvider)
        {
            urlProvider = PortalCrmConfigurationManager.CreateDependencyProvider(PortalName).GetDependency <IContentMapEntityUrlProvider>();

            if (urlProvider == null)
            {
                site = null;
                return(false);
            }

            var portal  = PortalContext;
            var website = portal.Website;

            if (!map.TryGetValue(website, out site))
            {
                return(false);
            }

            return(true);
        }
        private IDirectory GetDirectory(ContentMap contentMap, DirectoryContentHash hash)
        {
            var entityReference = hash.ToEntityReference();

            WebPageNode node;

            if (contentMap.TryGetValue(entityReference, out node))
            {
                return(new WebPageNodeDirectory(this, contentMap, node));
            }

            DirectoryType entityDirectoryType;

            if (EntityDirectoryTypes.TryGetValue(entityReference.LogicalName, out entityDirectoryType))
            {
                return(new EntityDirectory(this, entityReference, entityDirectoryType));
            }

            return(null);
        }
        /// <summary> The try assert. </summary>
        /// <param name="context"> The context. </param>
        /// <param name="entity"> The entity. </param>
        /// <param name="right"> The right. </param>
        /// <param name="dependencies"> The dependencies. </param>
        /// <param name="map"> The map. </param>
        /// <param name="useScope">Pass true if you need to determine web file permissions throught parent web page</param>
        /// <returns> The <see cref="bool"/>. </returns>
        public virtual bool TryAssert(OrganizationServiceContext context, Entity entity, CrmEntityRight right,
                                      CrmEntityCacheDependencyTrace dependencies, ContentMap map, bool useScope)
        {
            entity.AssertEntityName("adx_webpage");
            this.AddDependencies(
                dependencies,
                entity,
                new[] { "adx_webrole", "adx_webrole_contact", "adx_webrole_account", "adx_webpageaccesscontrolrule" });

            WebPageNode page;

            if (!map.TryGetValue(entity, out page))
            {
                // the website context is missing data
                ADXTrace.Instance.TraceError(TraceCategory.Application, string.Format("Failed to lookup the web page '{0}' ({1}).", entity.GetAttributeValue <string>("adx_name"), entity.Id));

                return(false);
            }

            dependencies.IsCacheable = false;

            return(this.TryAssert(page, right, useScope));
        }
Example #17
0
        private bool UserInRole(CrmEntityRight right, bool defaultIfNoRoles, Entity ideaForumEntity, CrmEntityCacheDependencyTrace dependencies, ContentMap map)
        {
            if (!Roles.Enabled)
            {
                ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Roles are not enabled for this application. Returning {0}.", defaultIfNoRoles));
                return(defaultIfNoRoles);
            }

            IEnumerable <Entity> roles = new List <Entity>();
            IdeaForumNode        ideaForumNode;

            if (!map.TryGetValue(ideaForumEntity, out ideaForumNode))
            {
                return(false);
            }

            if (right == CrmEntityRight.Read)
            {
                roles = ideaForumNode.WebRolesRead.Select(wr => wr.ToEntity());
            }
            else if (right == CrmEntityRight.Change)
            {
                roles = ideaForumNode.WebRolesWrite.Select(wr => wr.ToEntity());
            }

            if (!roles.Any())
            {
                ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Read is not restricted to any particular roles. Returning {0}.", defaultIfNoRoles));
                return(defaultIfNoRoles);
            }

            dependencies.AddEntityDependencies(roles);

            var userRoles = this.GetUserRoles();

            return(roles.Select(e => e.GetAttributeValue <string>("adx_name")).Intersect(userRoles, StringComparer.InvariantCulture).Any());
        }
Example #18
0
            private bool TestShortcutTarget(OrganizationServiceContext context, Entity entity, CrmEntityRight right, CrmEntityCacheDependencyTrace dependencies, ContentMap map)
            {
                ShortcutNode shortcut;

                if (map.TryGetValue(entity, out shortcut))
                {
                    if (!string.IsNullOrWhiteSpace(shortcut.ExternalUrl))
                    {
                        return(true);
                    }

                    if (shortcut.WebPage != null)
                    {
                        return(!shortcut.WebPage.IsReference && TestWebPage(context, shortcut.WebPage.ToEntity(), right, dependencies));
                    }

                    if (shortcut.WebFile != null)
                    {
                        return(!shortcut.WebFile.IsReference && TestWebFile(context, shortcut.WebFile.ToEntity(), right, dependencies));
                    }
                }

                return(base.TestShortcutTarget(context, entity, right, dependencies));
            }
        /// <summary>
        /// Selects all guids of web roles for the given entity.
        /// </summary>
        /// <param name="entityId">
        /// The webpage Id.
        /// </param>
        /// <param name="contentMap">
        /// The content map.
        /// </param>
        /// <returns>
        /// The <see cref="IEnumerable"/>. of the WebRole name associated to the webpage.
        /// </returns>
        private static IEnumerable <string> SelectAllWebRolesForWebpage(Guid entityId, ContentMap contentMap)
        {
            EntityNode entity;

            if (!contentMap.TryGetValue(new EntityReference("adx_webpage", entityId), out entity))
            {
                return(Enumerable.Empty <string>());
            }

            var webpage = entity as WebPageNode;

            if (webpage == null)
            {
                return(Enumerable.Empty <string>());
            }
            var webAccessRules = GetRulesForPage(webpage).ToList();

            // If the rule doesn't have a right associated to it then allow access
            var anyReadRestrictRules =
                webAccessRules.Any(
                    rule =>
            {
                if (rule.Right == null)
                {
                    return(false);
                }
                return(rule.Right.Value.ToEnum <ForumAccessPermissionProvider.RightOption>()
                       == ForumAccessPermissionProvider.RightOption.RestrictRead);
            });

            // If there is not read restrict rules specified then allow READ access.
            return(anyReadRestrictRules || (webpage.PublishingState.IsVisible == null || webpage.PublishingState.IsVisible.Value == false)
                                        ? webAccessRules.SelectMany(webPageAccessControlRuleNode => webPageAccessControlRuleNode.WebRoles,
                                                                    (webPageAccessControlRuleNode, webRole) => webRole.Name).Distinct()
                                        : new[] { AllowAccessDefaultValue });
        }
        private Entity GetWebsite(OrganizationServiceContext context, Entity entity, ContentMap map)
        {
            switch (entity.LogicalName)
            {
            case "adx_weblink":
                WebLinkNode link;
                if (map.TryGetValue(entity, out link))
                {
                    return(ToWebsite(context, link.WebLinkSet.Website));
                }
                break;

            case "adx_webpage":
                WebPageNode page;
                if (map.TryGetValue(entity, out page))
                {
                    return(ToWebsite(context, page.Website));
                }
                break;

            case "adx_weblinkset":
                WebLinkSetNode linkset;
                if (map.TryGetValue(entity, out linkset))
                {
                    return(ToWebsite(context, linkset.Website));
                }
                break;

            case "adx_webfile":
                WebFileNode file;
                if (map.TryGetValue(entity, out file))
                {
                    return(ToWebsite(context, file.Website));
                }
                break;

            case "adx_sitemarker":
                SiteMarkerNode marker;
                if (map.TryGetValue(entity, out marker))
                {
                    return(ToWebsite(context, marker.Website));
                }
                break;

            case "adx_pagetemplate":
                PageTemplateNode template;
                if (map.TryGetValue(entity, out template))
                {
                    return(ToWebsite(context, template.Website));
                }
                break;

            case "adx_contentsnippet":
                ContentSnippetNode snippet;
                if (map.TryGetValue(entity, out snippet))
                {
                    return(ToWebsite(context, snippet.Website));
                }
                break;

            case "adx_websitelanguage":
                WebsiteLanguageNode websiteLanguageNode;
                if (map.TryGetValue(entity, out websiteLanguageNode))
                {
                    return(ToWebsite(context, websiteLanguageNode.Website));
                }
                break;

            case "adx_ideaforum":
                IdeaForumNode ideaForumNode;
                if (map.TryGetValue(entity, out ideaForumNode))
                {
                    return(ToWebsite(context, ideaForumNode.Website));
                }
                break;

            case "adx_communityforum":
                ForumNode forumNode;
                if (map.TryGetValue(entity, out forumNode))
                {
                    return(ToWebsite(context, forumNode.Website));
                }
                break;

            case "adx_blog":
                BlogNode blogNode;
                if (map.TryGetValue(entity, out blogNode))
                {
                    return(ToWebsite(context, blogNode.Website));
                }
                break;

            case "adx_publishingstate":
                PublishingStateNode publishingStateNode;
                if (map.TryGetValue(entity, out publishingStateNode))
                {
                    return(ToWebsite(context, publishingStateNode.Website));
                }
                break;
            }

            return(base.GetWebsite(context, entity));
        }
        private SiteMapNode FindSiteMapNode(string rawUrl, ContentMap map, int counter = 0, bool excludeFromSecurityValidation = false)
        {
            using (PerformanceProfiler.Instance.StartMarker(PerformanceMarkerName.SiteMapProvider, PerformanceMarkerArea.Cms, PerformanceMarkerTagName.FindSiteMapNode))
            {
                counter++;
                WebsiteNode site;
                IContentMapEntityUrlProvider urlProvider;

                if (!TryGetWebsite(map, out site, out urlProvider))
                {
                    ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "FindSiteMapNode: (1)cannot find WebsiteNode");
                    return(base.FindSiteMapNode(rawUrl));
                }

                var    httpContext = HttpContext.Current;
                string currentNodeUrl;

                // Allow override of current site map node using special route param.
                if (httpContext != null &&
                    httpContext.Request.RawUrl == rawUrl &&
                    TryGetCurrentNodeUrlFromRouteData(httpContext, out currentNodeUrl) &&
                    currentNodeUrl != rawUrl && counter < 5000)
                {
                    ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "FindSiteMapNode: (2)override url");
                    return(FindSiteMapNode(currentNodeUrl, map, counter, excludeFromSecurityValidation));
                }

                var clientUrl = ExtractClientUrlFromRawUrl(rawUrl);

                // Find any possible SiteMarkerRoutes (or other IPortalContextRoutes) that match this path.
                string routeMatch  = RouteTable.Routes.GetPortalContextPath(map, site, clientUrl.Path);
                var    contextPath = routeMatch ?? clientUrl.Path;
                if (routeMatch != null)
                {
                    ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "FindSiteMapNode: (3)FOUND route");
                }

                var languageContext = httpContext.GetContextLanguageInfo();
                // If the URL matches a web page, try to look up that page and return a node.
                var mappingResult = ContentMapUrlMapping.LookupPageByUrlPath(site, contextPath, ContentMapUrlMapping.WebPageLookupOptions.LanguageContentOnly, languageContext);

                if (mappingResult.Node != null && mappingResult.IsUnique)
                {
                    ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "FindSiteMapNode: (4)FOUND PAGE");
                    return(GetAccessibleNodeOrAccessDeniedNode(map, mappingResult.Node, urlProvider, excludeFromSecurityValidation));
                }
                else if (!mappingResult.IsUnique)
                {
                    return(GetNotFoundNode(map, site, urlProvider));
                }

                // If the URL matches a web file, try to look up that file and return a node.
                var file = ContentMapUrlMapping.LookupFileByUrlPath(site, clientUrl.Path, languageContext);

                if (file != null)
                {
                    ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "FindSiteMapNode: (5)FOUND FILE");
                    return(GetAccessibleNodeOrAccessDeniedNode(map, file, urlProvider, excludeFromSecurityValidation));
                }

                // If there is a pageid Guid on the querystring, try to look up a web page by
                // that ID and return a node.
                Guid pageid;

                if (TryParseGuid(clientUrl.QueryString["pageid"], out pageid))
                {
                    WebPageNode pageById;

                    if (map.TryGetValue(new EntityReference("adx_webpage", pageid), out pageById))
                    {
                        ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "FindSiteMapNode: (6)FOUND pageID");
                        return(GetAccessibleNodeOrAccessDeniedNode(map, pageById, urlProvider, excludeFromSecurityValidation));
                    }
                }

                // If the above lookups failed, try find a node in any other site map providers.
                foreach (SiteMapProvider subProvider in SiteMap.Providers)
                {
                    // Skip this provider if it is the same as this one.
                    if (subProvider.Name == Name)
                    {
                        continue;
                    }

                    // Check if the provider has solution dependencies
                    var solutionDependent = subProvider as ISolutionDependent;

                    if (solutionDependent != null)
                    {
                        if (map.Solution.Solutions.Intersect(solutionDependent.RequiredSolutions).Count() != solutionDependent.RequiredSolutions.Count())
                        {
                            continue;
                        }
                    }

                    var node = subProvider.FindSiteMapNode(clientUrl.PathWithQueryString);

                    if (node != null)
                    {
                        ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "FindSiteMapNode: (7)FOUND other provider");
                        return(node);
                    }
                }

                ADXTrace.Instance.TraceInfo(TraceCategory.Monitoring, "FindSiteMapNode: (8)NOT FOUND");
                return(GetNotFoundNode(map, site, urlProvider));
            }
        }
        /// <summary>
        /// Select all the forums web roles.
        /// </summary>
        /// <param name="entityId">
        /// The entity id.
        /// </param>
        /// <param name="contentMap">
        /// The content map.
        /// </param>
        /// <returns>
        /// The <see cref="IEnumerable"/> of web roles associated to the forum.
        /// </returns>
        private static IEnumerable <string> SelectAllForumsWebRoles(Guid entityId, ContentMap contentMap)
        {
            EntityNode entity;

            // Get the Forums from the content map
            if (!contentMap.TryGetValue(new EntityReference("adx_communityforum", entityId), out entity))
            {
                return(Enumerable.Empty <string>());
            }

            var forum = entity as ForumNode;

            if (forum == null)
            {
                return(Enumerable.Empty <string>());
            }

            var changeRules =
                forum.ForumAccessPermissions.Where(fa => fa.Right == ForumAccessPermissionNode.RightOption.GrantChange)
                .SelectMany(fa => fa.WebRoles.Select(wr => wr.Name));

            var readRules =
                forum.ForumAccessPermissions.Where(fa => fa.Right == ForumAccessPermissionNode.RightOption.RestrictRead)
                .SelectMany(fa => fa.WebRoles.Select(wr => wr.Name)).ToList();

            bool anyInheritedReadRestrictRules = false;

            // If it has a parent page we will need to inspect to see if they have different read rules.
            if (forum.ParentPage != null)
            {
                var parentPageWebRoles = GetRulesForPage(forum.ParentPage).Distinct().ToList();
                anyInheritedReadRestrictRules =
                    parentPageWebRoles.Any(
                        rule =>
                {
                    if (rule.Right == null)
                    {
                        return(false);
                    }
                    return(rule.Right.Value.ToEnum <ForumAccessPermissionProvider.RightOption>()
                           == ForumAccessPermissionProvider.RightOption.RestrictRead);
                });

                // If Both the webpage tree do not have read restrict rules then give access to all.
                var parentPageWebRoleNames = anyInheritedReadRestrictRules || readRules.Any()
                                                ? parentPageWebRoles.SelectMany(
                    webPageAccessControlRuleNode => webPageAccessControlRuleNode.WebRoles,
                    (webPageAccessControlRuleNode, webRole) => webRole.Name).Distinct()
                                                : new[] { AllowAccessDefaultValue };

                // If there are no read restrict rules then we just follow the parents roles and change roles
                if (!readRules.Any() && !anyInheritedReadRestrictRules)
                {
                    return(changeRules.Concat(parentPageWebRoleNames).Distinct());
                }

                readRules = parentPageWebRoleNames.Union(readRules).ToList();
            }

            // Since it didn't have a parent page make sure there isn't a read restrict rule if no then give access to all.
            return(readRules.Any() || anyInheritedReadRestrictRules?changeRules.Concat(readRules).Distinct() : new[] { AllowAccessDefaultValue });
        }
Example #23
0
        private EntityNode Select(Guid id, ContentMap contentMap)
        {
            EntityNode page;

            return(!contentMap.TryGetValue(new EntityReference("adx_webpage", id), out page) ? null : page);
        }
        protected override bool TryAssert(OrganizationServiceContext context, Entity forum, CrmEntityRight right, CrmEntityCacheDependencyTrace dependencies, ContentMap map)
        {
            forum.AssertEntityName("adx_communityforum");

            ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Testing right {0} on forum '{1}' ({2}).", right, forum.GetAttributeValue <string>("adx_name"), forum.Id));

            this.AddDependencies(dependencies, forum, new [] { "adx_webrole", "adx_communityforumaccesspermission" });

            if (!Roles.Enabled)
            {
                ADXTrace.Instance.TraceInfo(TraceCategory.Application, "Roles are not enabled for this application. Allowing Read, but not Change.");

                // If roles are not enabled on the site, grant Read, deny Change.
                return(right == CrmEntityRight.Read);
            }

            var userRoles = this.GetUserRoles();

            // Get all rules applicable to the forum, grouping equivalent rules. (Rules that
            // target the same forum and confer the same right are equivalent.)
            var ruleGroupings = from rule in this.GetRulesApplicableToForum(forum, dependencies, map)
                                let forumReference = rule.GetAttributeValue <EntityReference>("adx_forumid")
                                                     let rightOption = rule.GetAttributeValue <OptionSetValue>("adx_right")
                                                                       where forumReference != null && rightOption != null
                                                                       group rule by new { ForumID = forumReference.Id, Right = ParseRightOption(rightOption.Value) } into ruleGrouping
            select ruleGrouping;

            var websiteReference = forum.GetAttributeValue <EntityReference>("adx_websiteid");

            // Order the rule groupings so that all GrantChange rules will be evaluated first.
            ruleGroupings = ruleGroupings.OrderByDescending(grouping => grouping.Key.Right, new RightOptionComparer());

            foreach (var ruleGrouping in ruleGroupings)
            {
                // Collect the names of all the roles that apply to this rule grouping
                var ruleGroupingRoles = ruleGrouping.SelectMany(rule => GetRolesForGrouping(map, rule, websiteReference));

                // Determine if the user belongs to any of the roles that apply to this rule grouping
                var userIsInAnyRoleForThisRule = ruleGroupingRoles.Any(role => userRoles.Any(userRole => userRole == role));

                // If the user belongs to one of the roles...
                if (userIsInAnyRoleForThisRule)
                {
                    // ...and the rule is GrantChange...
                    if (ruleGrouping.Key.Right == RightOption.GrantChange)
                    {
                        ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("User has right Change on forum ({0}). Permission granted.", ruleGrouping.Key.ForumID));

                        // ...the user has all rights.
                        return(true);
                    }
                }
                // If the user does not belong to any of the roles, the rule restricts read, and the desired right
                // is read...
                else if (ruleGrouping.Key.Right == RightOption.RestrictRead && right == CrmEntityRight.Read)
                {
                    ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("User does not have right Read due to read restriction on forum ({0}). Permission denied.", ruleGrouping.Key.ForumID));

                    // ...the user has no right.
                    return(false);
                }
            }

            // If none of the above rules apply, assert on parent webpage.
            var         parentWebPage = forum.GetAttributeValue <EntityReference>("adx_parentpageid");
            WebPageNode parentPageNode;

            map.TryGetValue(parentWebPage, out parentPageNode);

            // If there is no parent web page, grant Read by default, and deny Change.
            if (parentWebPage == null || parentPageNode == null)
            {
                ADXTrace.Instance.TraceInfo(TraceCategory.Application, "No access control rules apply to the current user and forum. Allowing Read, but not Change.");

                return(right == CrmEntityRight.Read);
            }

            ADXTrace.Instance.TraceInfo(TraceCategory.Application, "No access control rules apply to the current user and forum. Asserting right on parent web page.");

            return(this._webPageAccessControlProvider.TryAssert(context, parentPageNode.ToEntity(), right, dependencies));
        }