protected override bool Validate(OrganizationServiceContext context, CrmEntitySearchResult result) { // With permissions now indexed, invalid results should have been filtered out index time. // Monitor whether this is true or whether the permission indexing is missing corner cases. if (!base.Validate(context, result)) { return(false); } if (result.Url == null) { ADXTrace.Instance.TraceWarning(TraceCategory.Application, string.Format("Search result had invalid URL. Logical name: {0}, ID: {1}", EntityNamePrivacy.GetEntityName(result.EntityLogicalName), result.EntityID)); return(false); } if (!ValidateCmsSecurityProvider(context, result)) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Search result failed CMS security check. Logical name: {0}, ID: {1}", EntityNamePrivacy.GetEntityName(result.EntityLogicalName), result.EntityID)); if (!ValidateEntityPermission(context, result)) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Search result failed entity permissions security check. Logical name: {0}, ID: {1}", EntityNamePrivacy.GetEntityName(result.EntityLogicalName), result.EntityID)); return(false); } } // Checking products and CALs for a full page of results can be costly // Only check if explicitly enabled (e.g. because a customer is having issues with CAL/product indexing) if (FeatureCheckHelper.IsFeatureEnabled(FeatureNames.CALProductSearchPostFiltering)) { var contentAccessLevelProvider = new ContentAccessLevelProvider(); var productAccessProvider = new ProductAccessProvider(); if (!ValidateContentAccessLevelAndProducts(context, result, contentAccessLevelProvider, productAccessProvider)) { ADXTrace.Instance.TraceError(TraceCategory.Application, string.Format("Search result failed CAL or product filtering. Logical name: {0}, ID: {1}", EntityNamePrivacy.GetEntityName(result.EntityLogicalName), result.EntityID)); return(false); } } return(true); }
/// <summary> /// Validates the content access level and product filtering. /// </summary> /// <param name="serviceContext">The service context.</param> /// <param name="result">The result.</param> /// <returns>Boolean</returns> private bool ValidateContentAccessLevelAndProducts(OrganizationServiceContext serviceContext, CrmEntitySearchResult result, ContentAccessLevelProvider contentAccessLevelProvider, ProductAccessProvider productAccessProvider) { if (result == null || result.EntityID == null) { return(false); } // Content access levels/products will only filter knowledge articles if (result.EntityLogicalName != "knowledgearticle") { return(true); } var baseFetch = string.Format(@" <fetch mapping='logical'> <entity name='knowledgearticle'> <filter type='and'> <condition attribute='knowledgearticleid' operator='eq' value='{0}' /> </filter> </entity> </fetch>" , result.EntityID); if (!contentAccessLevelProvider.IsEnabled() && !productAccessProvider.IsEnabled()) { return(true); } Fetch filterCheckFetch = Fetch.Parse(baseFetch); contentAccessLevelProvider.TryApplyRecordLevelFiltersToFetch(CrmEntityPermissionRight.Read, filterCheckFetch); productAccessProvider.TryApplyRecordLevelFiltersToFetch(CrmEntityPermissionRight.Read, filterCheckFetch); // If there are no results, user didn't have access to products or CALs associated to article var response = (RetrieveMultipleResponse)serviceContext.Execute(filterCheckFetch.ToRetrieveMultipleRequest()); return(response.EntityCollection != null && response.EntityCollection.Entities.Any()); }
private bool ValidateEntityPermission(OrganizationServiceContext serviceContext, CrmEntitySearchResult result) { if (!AdxstudioCrmConfigurationManager.GetCrmSection().ContentMap.Enabled) { return(false); } var permissionResult = new CrmEntityPermissionProvider(PortalName).TryAssert(serviceContext, result.Entity); return(permissionResult.RulesExist && permissionResult.CanRead); }
private bool ValidateCmsSecurityProvider(OrganizationServiceContext serviceContext, CrmEntitySearchResult result) { return(PortalCrmConfigurationManager.CreateCrmEntitySecurityProvider(PortalName) .TryAssert(serviceContext, result.Entity, CrmEntityRight.Read)); }
public virtual ICrmEntitySearchResult GetResult(Document document, float score, int number) { if (document == null) { throw new ArgumentNullException("document"); } var logicalNameField = document.GetField(Index.LogicalNameFieldName); if (logicalNameField == null || !logicalNameField.IsStored) { return(null); } var logicalName = logicalNameField.StringValue; var primaryKeyLogicalNameField = document.GetField(Index.PrimaryKeyLogicalNameFieldName); if (primaryKeyLogicalNameField == null || !primaryKeyLogicalNameField.IsStored) { return(null); } var primaryKeyPropertyName = primaryKeyLogicalNameField.StringValue; var context = Index.DataContext; var primaryKeyField = document.GetField(Index.PrimaryKeyFieldName); if (primaryKeyField == null || !primaryKeyField.IsStored) { return(null); } var primaryKey = new Guid(primaryKeyField.StringValue); var titleField = document.GetField(Index.TitleFieldName); var title = string.Empty; if (logicalName != "annotation") { if (titleField == null || !titleField.IsStored) { return(null); } title = titleField.StringValue; } var entity = context.CreateQuery(logicalName).FirstOrDefault(e => e.GetAttributeValue <Guid>(primaryKeyPropertyName) == primaryKey); if (entity == null) { return(null); } var url = GetUrl(context, document, score, number, entity); var result = new CrmEntitySearchResult(entity, score, number, title, url); if (!Validate(context, result)) { return(null); } result.Fragment = FragmentProvider.GetFragment(document); return(result); }
protected virtual bool Validate(OrganizationServiceContext context, CrmEntitySearchResult result) { return(true); }