Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -947,6 +947,10 @@ private void configureContainerResolvers(final RuntimeWiring.Builder builder) {
typeWiring ->
typeWiring
.dataFetcher("relationships", new EntityRelationshipsResultResolver(graphClient))
.dataFetcher(
"relatedDocuments",
new com.linkedin.datahub.graphql.resolvers.knowledge.RelatedDocumentsResolver(
documentService, entityClient, groupService))
.dataFetcher("entities", new ContainerEntitiesResolver(entityClient))
.dataFetcher("privileges", new EntityPrivilegesResolver(entityClient))
.dataFetcher(
Expand Down Expand Up @@ -1749,6 +1753,10 @@ private void configureDatasetResolvers(final RuntimeWiring.Builder builder) {
typeWiring
.dataFetcher(
"relationships", new EntityRelationshipsResultResolver(graphClient))
.dataFetcher(
"relatedDocuments",
new com.linkedin.datahub.graphql.resolvers.knowledge
.RelatedDocumentsResolver(documentService, entityClient, groupService))
.dataFetcher("browsePaths", new EntityBrowsePathsResolver(this.datasetType))
.dataFetcher(
"lineage",
Expand Down Expand Up @@ -1975,7 +1983,11 @@ private void configureGlossaryTermResolvers(final RuntimeWiring.Builder builder)
.dataFetcher("privileges", new EntityPrivilegesResolver(entityClient))
.dataFetcher(
"aspects", new WeaklyTypedAspectsResolver(entityClient, entityRegistry))
.dataFetcher("exists", new EntityExistsResolver(entityService)));
.dataFetcher("exists", new EntityExistsResolver(entityService))
.dataFetcher(
"relatedDocuments",
new com.linkedin.datahub.graphql.resolvers.knowledge.RelatedDocumentsResolver(
documentService, entityClient, groupService)));
}

private void configureGlossaryNodeResolvers(final RuntimeWiring.Builder builder) {
Expand All @@ -1991,7 +2003,11 @@ private void configureGlossaryNodeResolvers(final RuntimeWiring.Builder builder)
"glossaryChildrenSearch",
new GlossaryChildrenSearchResolver(this.entityClient, this.viewService))
.dataFetcher(
"aspects", new WeaklyTypedAspectsResolver(entityClient, entityRegistry)));
"aspects", new WeaklyTypedAspectsResolver(entityClient, entityRegistry))
.dataFetcher(
"relatedDocuments",
new com.linkedin.datahub.graphql.resolvers.knowledge.RelatedDocumentsResolver(
documentService, entityClient, groupService)));
}

private void configureSchemaFieldResolvers(final RuntimeWiring.Builder builder) {
Expand Down Expand Up @@ -2216,6 +2232,10 @@ private void configureDashboardResolvers(final RuntimeWiring.Builder builder) {
typeWiring ->
typeWiring
.dataFetcher("relationships", new EntityRelationshipsResultResolver(graphClient))
.dataFetcher(
"relatedDocuments",
new com.linkedin.datahub.graphql.resolvers.knowledge.RelatedDocumentsResolver(
documentService, entityClient, groupService))
.dataFetcher("browsePaths", new EntityBrowsePathsResolver(this.dashboardType))
.dataFetcher(
"lineage",
Expand Down Expand Up @@ -2347,6 +2367,10 @@ private void configureChartResolvers(final RuntimeWiring.Builder builder) {
typeWiring ->
typeWiring
.dataFetcher("relationships", new EntityRelationshipsResultResolver(graphClient))
.dataFetcher(
"relatedDocuments",
new com.linkedin.datahub.graphql.resolvers.knowledge.RelatedDocumentsResolver(
documentService, entityClient, groupService))
.dataFetcher("browsePaths", new EntityBrowsePathsResolver(this.chartType))
.dataFetcher(
"aspects", new WeaklyTypedAspectsResolver(entityClient, entityRegistry))
Expand Down Expand Up @@ -2547,6 +2571,10 @@ private void configureDataJobResolvers(final RuntimeWiring.Builder builder) {
typeWiring
.dataFetcher(
"relationships", new EntityRelationshipsResultResolver(graphClient))
.dataFetcher(
"relatedDocuments",
new com.linkedin.datahub.graphql.resolvers.knowledge
.RelatedDocumentsResolver(documentService, entityClient, groupService))
.dataFetcher("browsePaths", new EntityBrowsePathsResolver(this.dataJobType))
.dataFetcher(
"lineage",
Expand Down Expand Up @@ -2650,6 +2678,10 @@ private void configureDataFlowResolvers(final RuntimeWiring.Builder builder) {
typeWiring ->
typeWiring
.dataFetcher("relationships", new EntityRelationshipsResultResolver(graphClient))
.dataFetcher(
"relatedDocuments",
new com.linkedin.datahub.graphql.resolvers.knowledge.RelatedDocumentsResolver(
documentService, entityClient, groupService))
.dataFetcher("browsePaths", new EntityBrowsePathsResolver(this.dataFlowType))
.dataFetcher(
"lineage",
Expand Down Expand Up @@ -2706,6 +2738,10 @@ private void configureMLFeatureTableResolvers(final RuntimeWiring.Builder builde
typeWiring
.dataFetcher(
"relationships", new EntityRelationshipsResultResolver(graphClient))
.dataFetcher(
"relatedDocuments",
new com.linkedin.datahub.graphql.resolvers.knowledge
.RelatedDocumentsResolver(documentService, entityClient, groupService))
.dataFetcher(
"browsePaths", new EntityBrowsePathsResolver(this.mlFeatureTableType))
.dataFetcher(
Expand Down Expand Up @@ -2798,6 +2834,10 @@ private void configureMLFeatureTableResolvers(final RuntimeWiring.Builder builde
typeWiring
.dataFetcher(
"relationships", new EntityRelationshipsResultResolver(graphClient))
.dataFetcher(
"relatedDocuments",
new com.linkedin.datahub.graphql.resolvers.knowledge
.RelatedDocumentsResolver(documentService, entityClient, groupService))
.dataFetcher("browsePaths", new EntityBrowsePathsResolver(this.mlModelType))
.dataFetcher(
"lineage",
Expand Down Expand Up @@ -2846,6 +2886,10 @@ private void configureMLFeatureTableResolvers(final RuntimeWiring.Builder builde
typeWiring
.dataFetcher(
"relationships", new EntityRelationshipsResultResolver(graphClient))
.dataFetcher(
"relatedDocuments",
new com.linkedin.datahub.graphql.resolvers.knowledge
.RelatedDocumentsResolver(documentService, entityClient, groupService))
.dataFetcher(
"browsePaths", new EntityBrowsePathsResolver(this.mlModelGroupType))
.dataFetcher(
Expand Down Expand Up @@ -2879,6 +2923,10 @@ private void configureMLFeatureTableResolvers(final RuntimeWiring.Builder builde
typeWiring
.dataFetcher(
"relationships", new EntityRelationshipsResultResolver(graphClient))
.dataFetcher(
"relatedDocuments",
new com.linkedin.datahub.graphql.resolvers.knowledge
.RelatedDocumentsResolver(documentService, entityClient, groupService))
.dataFetcher(
"lineage",
new EntityLineageResultResolver(
Expand All @@ -2905,6 +2953,10 @@ private void configureMLFeatureTableResolvers(final RuntimeWiring.Builder builde
typeWiring
.dataFetcher(
"relationships", new EntityRelationshipsResultResolver(graphClient))
.dataFetcher(
"relatedDocuments",
new com.linkedin.datahub.graphql.resolvers.knowledge
.RelatedDocumentsResolver(documentService, entityClient, groupService))
.dataFetcher("privileges", new EntityPrivilegesResolver(entityClient))
.dataFetcher(
"lineage",
Expand Down Expand Up @@ -2951,7 +3003,11 @@ private void configureDomainResolvers(final RuntimeWiring.Builder builder) {
.dataFetcher("privileges", new EntityPrivilegesResolver(entityClient))
.dataFetcher(
"aspects", new WeaklyTypedAspectsResolver(entityClient, entityRegistry))
.dataFetcher("relationships", new EntityRelationshipsResultResolver(graphClient)));
.dataFetcher("relationships", new EntityRelationshipsResultResolver(graphClient))
.dataFetcher(
"relatedDocuments",
new com.linkedin.datahub.graphql.resolvers.knowledge.RelatedDocumentsResolver(
documentService, entityClient, groupService)));
builder.type(
"DomainAssociation",
typeWiring ->
Expand Down Expand Up @@ -3043,7 +3099,11 @@ private void configureDataProductResolvers(final RuntimeWiring.Builder builder)
.dataFetcher("privileges", new EntityPrivilegesResolver(entityClient))
.dataFetcher(
"aspects", new WeaklyTypedAspectsResolver(entityClient, entityRegistry))
.dataFetcher("relationships", new EntityRelationshipsResultResolver(graphClient)));
.dataFetcher("relationships", new EntityRelationshipsResultResolver(graphClient))
.dataFetcher(
"relatedDocuments",
new com.linkedin.datahub.graphql.resolvers.knowledge.RelatedDocumentsResolver(
documentService, entityClient, groupService)));
}

private void configureApplicationResolvers(final RuntimeWiring.Builder builder) {
Expand All @@ -3054,7 +3114,11 @@ private void configureApplicationResolvers(final RuntimeWiring.Builder builder)
.dataFetcher("privileges", new EntityPrivilegesResolver(entityClient))
.dataFetcher(
"aspects", new WeaklyTypedAspectsResolver(entityClient, entityRegistry))
.dataFetcher("relationships", new EntityRelationshipsResultResolver(graphClient)));
.dataFetcher("relationships", new EntityRelationshipsResultResolver(graphClient))
.dataFetcher(
"relatedDocuments",
new com.linkedin.datahub.graphql.resolvers.knowledge.RelatedDocumentsResolver(
documentService, entityClient, groupService)));
builder.type(
"ApplicationAssociation",
typeWiring ->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.linkedin.datahub.graphql.resolvers.knowledge;

import com.linkedin.metadata.query.filter.Condition;
import com.linkedin.metadata.query.filter.ConjunctiveCriterion;
import com.linkedin.metadata.query.filter.ConjunctiveCriterionArray;
import com.linkedin.metadata.query.filter.Criterion;
import com.linkedin.metadata.query.filter.CriterionArray;
import com.linkedin.metadata.query.filter.Filter;
import com.linkedin.metadata.utils.CriterionUtils;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;

/**
* Utility class for building document search filters with ownership constraints. Shared logic for
* SearchDocumentsResolver and ContextDocumentsResolver.
*/
public class DocumentSearchFilterUtils {

private DocumentSearchFilterUtils() {
// Utility class - prevent instantiation
}

/**
* Builds a combined filter with ownership constraints. The filter structure is: (user-filters AND
* PUBLISHED AND NOT-DRAFT) OR (user-filters AND UNPUBLISHED AND owned-by-user-or-groups AND
* NOT-DRAFT)
*
* <p>Drafts (documents with draftOf field set) are excluded by default from search results. They
* should only be accessed directly by URN or through the DocumentDrafts resolver.
*
* @param baseCriteria The base user criteria (without state filtering)
* @param userAndGroupUrns List of URNs for the current user and their groups
* @return The combined filter
*/
@Nonnull
public static Filter buildCombinedFilter(
@Nonnull List<Criterion> baseCriteria, @Nonnull List<String> userAndGroupUrns) {
// Build two conjunctive clauses:
// 1. Base filters AND PUBLISHED AND NOT-DRAFT
// 2. Base filters AND UNPUBLISHED AND owned-by-user-or-groups AND NOT-DRAFT

List<ConjunctiveCriterion> orClauses = new ArrayList<>();

// Create criterion to exclude drafts (draftOf field must be null/not set)
Criterion notDraftCriterion = new Criterion();
notDraftCriterion.setField("draftOf");
notDraftCriterion.setCondition(Condition.IS_NULL);

// Clause 1: Published documents (with user filters, excluding drafts)
List<Criterion> publishedCriteria = new ArrayList<>(baseCriteria);
publishedCriteria.add(CriterionUtils.buildCriterion("state", Condition.EQUAL, "PUBLISHED"));
publishedCriteria.add(notDraftCriterion);
orClauses.add(new ConjunctiveCriterion().setAnd(new CriterionArray(publishedCriteria)));

// Clause 2: Unpublished documents owned by user or their groups (with user filters, excluding
// drafts)
List<Criterion> unpublishedOwnedCriteria = new ArrayList<>(baseCriteria);
unpublishedOwnedCriteria.add(
CriterionUtils.buildCriterion("state", Condition.EQUAL, "UNPUBLISHED"));
unpublishedOwnedCriteria.add(
CriterionUtils.buildCriterion("owners", Condition.EQUAL, userAndGroupUrns));
// Create a new criterion instance for the second clause to avoid sharing mutable state
Criterion notDraftCriterion2 = new Criterion();
notDraftCriterion2.setField("draftOf");
notDraftCriterion2.setCondition(Condition.IS_NULL);
unpublishedOwnedCriteria.add(notDraftCriterion2);
orClauses.add(new ConjunctiveCriterion().setAnd(new CriterionArray(unpublishedOwnedCriteria)));

return new Filter().setOr(new ConjunctiveCriterionArray(orClauses));
}
}
Loading
Loading