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); }
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)); }
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()); }
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 }); }
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)); }