From edd2831caa612e4288f1938777d00830f59064cb Mon Sep 17 00:00:00 2001 From: Meenakshi Kamalaseshan Radha <62914384+mkamalas@users.noreply.github.com> Date: Sat, 28 Sep 2024 00:41:14 +0530 Subject: [PATCH] feat(auth) - Manage Children Glossary term authorization check for Owner, Domain, Remove link (#11337) --- .../datahub/graphql/GmsGraphQLEngine.java | 17 +++++++----- .../resolvers/domain/SetDomainResolver.java | 2 +- .../resolvers/domain/UnsetDomainResolver.java | 2 +- .../glossary/AddRelatedTermsResolver.java | 3 +-- .../DeleteGlossaryEntityResolver.java | 3 +-- .../glossary/RemoveRelatedTermsResolver.java | 3 +-- .../resolvers/mutate/AddLinkResolver.java | 17 +----------- .../resolvers/mutate/AddOwnerResolver.java | 4 ++- .../resolvers/mutate/AddOwnersResolver.java | 5 +++- .../mutate/BatchAddOwnersResolver.java | 4 ++- .../mutate/BatchRemoveOwnersResolver.java | 4 ++- .../mutate/BatchSetDomainResolver.java | 4 ++- .../resolvers/mutate/RemoveLinkResolver.java | 6 ++++- .../resolvers/mutate/RemoveOwnerResolver.java | 4 ++- .../resolvers/mutate/UpdateNameResolver.java | 6 ++--- .../resolvers/mutate/util/DomainUtils.java | 7 ++++- .../resolvers/mutate/util/GlossaryUtils.java | 15 +++++++++++ .../resolvers/mutate/util/OwnerUtils.java | 8 +++++- .../domain/BatchSetDomainResolverTest.java | 22 +++++++++++----- .../owner/AddOwnersResolverTest.java | 26 +++++++++++++------ .../owner/BatchAddOwnersResolverTest.java | 19 +++++++++----- .../owner/BatchRemoveOwnersResolverTest.java | 16 ++++++++---- 22 files changed, 127 insertions(+), 70 deletions(-) diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java index d38c1030b61be..5b265b6714452 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java @@ -1192,13 +1192,15 @@ private void configureMutationResolvers(final RuntimeWiring.Builder builder) { .dataFetcher( "updateDescription", new UpdateDescriptionResolver(entityService, this.entityClient)) - .dataFetcher("addOwner", new AddOwnerResolver(entityService)) - .dataFetcher("addOwners", new AddOwnersResolver(entityService)) - .dataFetcher("batchAddOwners", new BatchAddOwnersResolver(entityService)) - .dataFetcher("removeOwner", new RemoveOwnerResolver(entityService)) - .dataFetcher("batchRemoveOwners", new BatchRemoveOwnersResolver(entityService)) + .dataFetcher("addOwner", new AddOwnerResolver(entityService, entityClient)) + .dataFetcher("addOwners", new AddOwnersResolver(entityService, entityClient)) + .dataFetcher( + "batchAddOwners", new BatchAddOwnersResolver(entityService, entityClient)) + .dataFetcher("removeOwner", new RemoveOwnerResolver(entityService, entityClient)) + .dataFetcher( + "batchRemoveOwners", new BatchRemoveOwnersResolver(entityService, entityClient)) .dataFetcher("addLink", new AddLinkResolver(entityService, this.entityClient)) - .dataFetcher("removeLink", new RemoveLinkResolver(entityService)) + .dataFetcher("removeLink", new RemoveLinkResolver(entityService, entityClient)) .dataFetcher("addGroupMembers", new AddGroupMembersResolver(this.groupService)) .dataFetcher("removeGroupMembers", new RemoveGroupMembersResolver(this.groupService)) .dataFetcher("createGroup", new CreateGroupResolver(this.groupService)) @@ -1212,7 +1214,8 @@ private void configureMutationResolvers(final RuntimeWiring.Builder builder) { .dataFetcher("deleteDomain", new DeleteDomainResolver(entityClient)) .dataFetcher( "setDomain", new SetDomainResolver(this.entityClient, this.entityService)) - .dataFetcher("batchSetDomain", new BatchSetDomainResolver(this.entityService)) + .dataFetcher( + "batchSetDomain", new BatchSetDomainResolver(this.entityService, entityClient)) .dataFetcher( "updateDeprecation", new UpdateDeprecationResolver(this.entityClient, this.entityService)) diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/SetDomainResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/SetDomainResolver.java index 6ada447ca59ee..adbaae368a418 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/SetDomainResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/SetDomainResolver.java @@ -44,7 +44,7 @@ public CompletableFuture get(DataFetchingEnvironment environment) throw return GraphQLConcurrencyUtils.supplyAsync( () -> { if (!DomainUtils.isAuthorizedToUpdateDomainsForEntity( - environment.getContext(), entityUrn)) { + environment.getContext(), entityUrn, _entityClient)) { throw new AuthorizationException( "Unauthorized to perform this action. Please contact your DataHub administrator."); } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/UnsetDomainResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/UnsetDomainResolver.java index 783cf250a7ca6..b0bb206a8827b 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/UnsetDomainResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/domain/UnsetDomainResolver.java @@ -43,7 +43,7 @@ public CompletableFuture get(DataFetchingEnvironment environment) throw return GraphQLConcurrencyUtils.supplyAsync( () -> { if (!DomainUtils.isAuthorizedToUpdateDomainsForEntity( - environment.getContext(), entityUrn)) { + environment.getContext(), entityUrn, _entityClient)) { throw new AuthorizationException( "Unauthorized to perform this action. Please contact your DataHub administrator."); } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/glossary/AddRelatedTermsResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/glossary/AddRelatedTermsResolver.java index 1e99ea120354e..69ad8658b23ba 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/glossary/AddRelatedTermsResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/glossary/AddRelatedTermsResolver.java @@ -46,8 +46,7 @@ public CompletableFuture get(DataFetchingEnvironment environment) throw return GraphQLConcurrencyUtils.supplyAsync( () -> { - final Urn parentUrn = GlossaryUtils.getParentUrn(urn, context, _entityClient); - if (GlossaryUtils.canManageChildrenEntities(context, parentUrn, _entityClient)) { + if (GlossaryUtils.canUpdateGlossaryEntity(urn, context, _entityClient)) { try { final TermRelationshipType relationshipType = input.getRelationshipType(); final List termUrns = diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/glossary/DeleteGlossaryEntityResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/glossary/DeleteGlossaryEntityResolver.java index 26f0c61de1b0f..c663bd2cf9b9f 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/glossary/DeleteGlossaryEntityResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/glossary/DeleteGlossaryEntityResolver.java @@ -29,11 +29,10 @@ public CompletableFuture get(final DataFetchingEnvironment environment) throws Exception { final QueryContext context = environment.getContext(); final Urn entityUrn = Urn.createFromString(environment.getArgument("urn")); - final Urn parentNodeUrn = GlossaryUtils.getParentUrn(entityUrn, context, _entityClient); return GraphQLConcurrencyUtils.supplyAsync( () -> { - if (GlossaryUtils.canManageChildrenEntities(context, parentNodeUrn, _entityClient)) { + if (GlossaryUtils.canUpdateGlossaryEntity(entityUrn, context, _entityClient)) { if (!_entityService.exists(context.getOperationContext(), entityUrn, true)) { throw new RuntimeException(String.format("This urn does not exist: %s", entityUrn)); } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/glossary/RemoveRelatedTermsResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/glossary/RemoveRelatedTermsResolver.java index 59f820d7cbd36..4e1ffcc00cd89 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/glossary/RemoveRelatedTermsResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/glossary/RemoveRelatedTermsResolver.java @@ -42,8 +42,7 @@ public CompletableFuture get(DataFetchingEnvironment environment) throw return GraphQLConcurrencyUtils.supplyAsync( () -> { - final Urn parentUrn = GlossaryUtils.getParentUrn(urn, context, _entityClient); - if (GlossaryUtils.canManageChildrenEntities(context, parentUrn, _entityClient)) { + if (GlossaryUtils.canUpdateGlossaryEntity(urn, context, _entityClient)) { try { final TermRelationshipType relationshipType = input.getRelationshipType(); final List termUrnsToRemove = diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/AddLinkResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/AddLinkResolver.java index 5cffcd9c35c00..c71832b956a7c 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/AddLinkResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/AddLinkResolver.java @@ -11,7 +11,6 @@ import com.linkedin.datahub.graphql.resolvers.mutate.util.GlossaryUtils; import com.linkedin.datahub.graphql.resolvers.mutate.util.LinkUtils; import com.linkedin.entity.client.EntityClient; -import com.linkedin.metadata.Constants; import com.linkedin.metadata.entity.EntityService; import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; @@ -36,7 +35,7 @@ public CompletableFuture get(DataFetchingEnvironment environment) throw Urn targetUrn = Urn.createFromString(input.getResourceUrn()); if (!LinkUtils.isAuthorizedToUpdateLinks(context, targetUrn) - && !canUpdateGlossaryEntityLinks(targetUrn, context)) { + && !GlossaryUtils.canUpdateGlossaryEntity(targetUrn, context, _entityClient)) { throw new AuthorizationException( "Unauthorized to perform this action. Please contact your DataHub administrator."); } @@ -70,18 +69,4 @@ public CompletableFuture get(DataFetchingEnvironment environment) throw this.getClass().getSimpleName(), "get"); } - - // Returns whether this is a glossary entity and whether you can edit this glossary entity with - // the - // Manage all children or Manage direct children privileges - private boolean canUpdateGlossaryEntityLinks(Urn targetUrn, QueryContext context) { - final boolean isGlossaryEntity = - targetUrn.getEntityType().equals(Constants.GLOSSARY_TERM_ENTITY_NAME) - || targetUrn.getEntityType().equals(Constants.GLOSSARY_NODE_ENTITY_NAME); - if (!isGlossaryEntity) { - return false; - } - final Urn parentNodeUrn = GlossaryUtils.getParentUrn(targetUrn, context, _entityClient); - return GlossaryUtils.canManageChildrenEntities(context, parentNodeUrn, _entityClient); - } } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/AddOwnerResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/AddOwnerResolver.java index 7c0f7b3757ee9..db58236a4e615 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/AddOwnerResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/AddOwnerResolver.java @@ -11,6 +11,7 @@ import com.linkedin.datahub.graphql.generated.OwnerInput; import com.linkedin.datahub.graphql.generated.ResourceRefInput; import com.linkedin.datahub.graphql.resolvers.mutate.util.OwnerUtils; +import com.linkedin.entity.client.EntityClient; import com.linkedin.metadata.entity.EntityService; import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; @@ -23,6 +24,7 @@ public class AddOwnerResolver implements DataFetcher> { private final EntityService _entityService; + private final EntityClient _entityClient; @Override public CompletableFuture get(DataFetchingEnvironment environment) throws Exception { @@ -41,7 +43,7 @@ public CompletableFuture get(DataFetchingEnvironment environment) throw } OwnerInput ownerInput = ownerInputBuilder.build(); - OwnerUtils.validateAuthorizedToUpdateOwners(context, targetUrn); + OwnerUtils.validateAuthorizedToUpdateOwners(context, targetUrn, _entityClient); return GraphQLConcurrencyUtils.supplyAsync( () -> { diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/AddOwnersResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/AddOwnersResolver.java index ade4e7b744801..329b0abf31149 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/AddOwnersResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/AddOwnersResolver.java @@ -11,6 +11,7 @@ import com.linkedin.datahub.graphql.generated.OwnerInput; import com.linkedin.datahub.graphql.generated.ResourceRefInput; import com.linkedin.datahub.graphql.resolvers.mutate.util.OwnerUtils; +import com.linkedin.entity.client.EntityClient; import com.linkedin.metadata.entity.EntityService; import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; @@ -24,6 +25,7 @@ public class AddOwnersResolver implements DataFetcher> { private final EntityService _entityService; + private final EntityClient _entityClient; @Override public CompletableFuture get(DataFetchingEnvironment environment) throws Exception { @@ -35,7 +37,8 @@ public CompletableFuture get(DataFetchingEnvironment environment) throw return GraphQLConcurrencyUtils.supplyAsync( () -> { - OwnerUtils.validateAuthorizedToUpdateOwners(environment.getContext(), targetUrn); + OwnerUtils.validateAuthorizedToUpdateOwners( + environment.getContext(), targetUrn, _entityClient); OwnerUtils.validateAddOwnerInput( context.getOperationContext(), owners, targetUrn, _entityService); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/BatchAddOwnersResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/BatchAddOwnersResolver.java index 28daef1b11062..3f0f5e0b9edcf 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/BatchAddOwnersResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/BatchAddOwnersResolver.java @@ -11,6 +11,7 @@ import com.linkedin.datahub.graphql.generated.ResourceRefInput; import com.linkedin.datahub.graphql.resolvers.mutate.util.LabelUtils; import com.linkedin.datahub.graphql.resolvers.mutate.util.OwnerUtils; +import com.linkedin.entity.client.EntityClient; import com.linkedin.metadata.entity.EntityService; import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; @@ -27,6 +28,7 @@ public class BatchAddOwnersResolver implements DataFetcher> { private final EntityService _entityService; + private final EntityClient _entityClient; @Override public CompletableFuture get(DataFetchingEnvironment environment) throws Exception { @@ -80,7 +82,7 @@ private void validateInputResource( "Malformed input provided: owners cannot be applied to subresources."); } - OwnerUtils.validateAuthorizedToUpdateOwners(context, resourceUrn); + OwnerUtils.validateAuthorizedToUpdateOwners(context, resourceUrn, _entityClient); LabelUtils.validateResource( opContext, resourceUrn, diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/BatchRemoveOwnersResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/BatchRemoveOwnersResolver.java index 5aaace4e21e9c..4772b3ef27ac9 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/BatchRemoveOwnersResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/BatchRemoveOwnersResolver.java @@ -10,6 +10,7 @@ import com.linkedin.datahub.graphql.generated.ResourceRefInput; import com.linkedin.datahub.graphql.resolvers.mutate.util.LabelUtils; import com.linkedin.datahub.graphql.resolvers.mutate.util.OwnerUtils; +import com.linkedin.entity.client.EntityClient; import com.linkedin.metadata.entity.EntityService; import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; @@ -24,6 +25,7 @@ public class BatchRemoveOwnersResolver implements DataFetcher> { private final EntityService _entityService; + private final EntityClient _entityClient; @Override public CompletableFuture get(DataFetchingEnvironment environment) throws Exception { @@ -72,7 +74,7 @@ private void validateInputResource(ResourceRefInput resource, QueryContext conte "Malformed input provided: owners cannot be removed from subresources."); } - OwnerUtils.validateAuthorizedToUpdateOwners(context, resourceUrn); + OwnerUtils.validateAuthorizedToUpdateOwners(context, resourceUrn, _entityClient); LabelUtils.validateResource( context.getOperationContext(), resourceUrn, diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/BatchSetDomainResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/BatchSetDomainResolver.java index abbeed29545e4..3cf8e801d4171 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/BatchSetDomainResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/BatchSetDomainResolver.java @@ -11,6 +11,7 @@ import com.linkedin.datahub.graphql.generated.ResourceRefInput; import com.linkedin.datahub.graphql.resolvers.mutate.util.DomainUtils; import com.linkedin.datahub.graphql.resolvers.mutate.util.LabelUtils; +import com.linkedin.entity.client.EntityClient; import com.linkedin.metadata.entity.EntityService; import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; @@ -28,6 +29,7 @@ public class BatchSetDomainResolver implements DataFetcher> { private final EntityService _entityService; + private final EntityClient _entityClient; @Override public CompletableFuture get(DataFetchingEnvironment environment) throws Exception { @@ -74,7 +76,7 @@ private void validateInputResources(List resources, QueryConte private void validateInputResource(ResourceRefInput resource, QueryContext context) { final Urn resourceUrn = UrnUtils.getUrn(resource.getResourceUrn()); - if (!DomainUtils.isAuthorizedToUpdateDomainsForEntity(context, resourceUrn)) { + if (!DomainUtils.isAuthorizedToUpdateDomainsForEntity(context, resourceUrn, _entityClient)) { throw new AuthorizationException( "Unauthorized to perform this action. Please contact your DataHub administrator."); } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/RemoveLinkResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/RemoveLinkResolver.java index e047a24a0adaa..584a0e3e9c2aa 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/RemoveLinkResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/RemoveLinkResolver.java @@ -8,7 +8,9 @@ import com.linkedin.datahub.graphql.concurrency.GraphQLConcurrencyUtils; import com.linkedin.datahub.graphql.exception.AuthorizationException; import com.linkedin.datahub.graphql.generated.RemoveLinkInput; +import com.linkedin.datahub.graphql.resolvers.mutate.util.GlossaryUtils; import com.linkedin.datahub.graphql.resolvers.mutate.util.LinkUtils; +import com.linkedin.entity.client.EntityClient; import com.linkedin.metadata.entity.EntityService; import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; @@ -21,6 +23,7 @@ public class RemoveLinkResolver implements DataFetcher> { private final EntityService _entityService; + private final EntityClient _entityClient; @Override public CompletableFuture get(DataFetchingEnvironment environment) throws Exception { @@ -31,7 +34,8 @@ public CompletableFuture get(DataFetchingEnvironment environment) throw String linkUrl = input.getLinkUrl(); Urn targetUrn = Urn.createFromString(input.getResourceUrn()); - if (!LinkUtils.isAuthorizedToUpdateLinks(context, targetUrn)) { + if (!LinkUtils.isAuthorizedToUpdateLinks(context, targetUrn) + && !GlossaryUtils.canUpdateGlossaryEntity(targetUrn, context, _entityClient)) { throw new AuthorizationException( "Unauthorized to perform this action. Please contact your DataHub administrator."); } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/RemoveOwnerResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/RemoveOwnerResolver.java index 8d14884885572..dfb4778644321 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/RemoveOwnerResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/RemoveOwnerResolver.java @@ -10,6 +10,7 @@ import com.linkedin.datahub.graphql.generated.RemoveOwnerInput; import com.linkedin.datahub.graphql.generated.ResourceRefInput; import com.linkedin.datahub.graphql.resolvers.mutate.util.OwnerUtils; +import com.linkedin.entity.client.EntityClient; import com.linkedin.metadata.entity.EntityService; import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; @@ -22,6 +23,7 @@ public class RemoveOwnerResolver implements DataFetcher> { private final EntityService _entityService; + private final EntityClient _entityClient; @Override public CompletableFuture get(DataFetchingEnvironment environment) throws Exception { @@ -36,7 +38,7 @@ public CompletableFuture get(DataFetchingEnvironment environment) throw ? null : Urn.createFromString(input.getOwnershipTypeUrn()); - OwnerUtils.validateAuthorizedToUpdateOwners(context, targetUrn); + OwnerUtils.validateAuthorizedToUpdateOwners(context, targetUrn, _entityClient); return GraphQLConcurrencyUtils.supplyAsync( () -> { diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/UpdateNameResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/UpdateNameResolver.java index ad6dbbe635ed1..87aad3f767d95 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/UpdateNameResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/UpdateNameResolver.java @@ -87,8 +87,7 @@ public CompletableFuture get(DataFetchingEnvironment environment) throw private Boolean updateGlossaryTermName( Urn targetUrn, UpdateNameInput input, QueryContext context) { - final Urn parentNodeUrn = GlossaryUtils.getParentUrn(targetUrn, context, _entityClient); - if (GlossaryUtils.canManageChildrenEntities(context, parentNodeUrn, _entityClient)) { + if (GlossaryUtils.canUpdateGlossaryEntity(targetUrn, context, _entityClient)) { try { GlossaryTermInfo glossaryTermInfo = (GlossaryTermInfo) @@ -123,8 +122,7 @@ private Boolean updateGlossaryTermName( private Boolean updateGlossaryNodeName( Urn targetUrn, UpdateNameInput input, QueryContext context) { - final Urn parentNodeUrn = GlossaryUtils.getParentUrn(targetUrn, context, _entityClient); - if (GlossaryUtils.canManageChildrenEntities(context, parentNodeUrn, _entityClient)) { + if (GlossaryUtils.canUpdateGlossaryEntity(targetUrn, context, _entityClient)) { try { GlossaryNodeInfo glossaryNodeInfo = (GlossaryNodeInfo) diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/util/DomainUtils.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/util/DomainUtils.java index 4224f75773200..bf94585467814 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/util/DomainUtils.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/util/DomainUtils.java @@ -60,7 +60,12 @@ public class DomainUtils { private DomainUtils() {} public static boolean isAuthorizedToUpdateDomainsForEntity( - @Nonnull QueryContext context, Urn entityUrn) { + @Nonnull QueryContext context, Urn entityUrn, EntityClient entityClient) { + + if (GlossaryUtils.canUpdateGlossaryEntity(entityUrn, context, entityClient)) { + return true; + } + final DisjunctivePrivilegeGroup orPrivilegeGroups = new DisjunctivePrivilegeGroup( ImmutableList.of( diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/util/GlossaryUtils.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/util/GlossaryUtils.java index 0d8e505a948e5..9ff908b4ee37f 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/util/GlossaryUtils.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/util/GlossaryUtils.java @@ -36,6 +36,21 @@ public static boolean canManageGlossaries(@Nonnull QueryContext context) { context.getOperationContext(), PoliciesConfig.MANAGE_GLOSSARIES_PRIVILEGE); } + // Returns whether this is a glossary entity and whether you can edit this glossary entity with + // the + // Manage all children or Manage direct children privileges + public static boolean canUpdateGlossaryEntity( + Urn targetUrn, QueryContext context, EntityClient entityClient) { + final boolean isGlossaryEntity = + targetUrn.getEntityType().equals(Constants.GLOSSARY_TERM_ENTITY_NAME) + || targetUrn.getEntityType().equals(Constants.GLOSSARY_NODE_ENTITY_NAME); + if (!isGlossaryEntity) { + return false; + } + final Urn parentNodeUrn = GlossaryUtils.getParentUrn(targetUrn, context, entityClient); + return GlossaryUtils.canManageChildrenEntities(context, parentNodeUrn, entityClient); + } + /** * Returns true if the current user is able to create, delete, or move Glossary Terms and Nodes * under a parent Node. They can do this with either the global MANAGE_GLOSSARIES privilege, or if diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/util/OwnerUtils.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/util/OwnerUtils.java index 2f2b52f7ab586..b9a12a19f617a 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/util/OwnerUtils.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/mutate/util/OwnerUtils.java @@ -20,6 +20,7 @@ import com.linkedin.datahub.graphql.generated.OwnerInput; import com.linkedin.datahub.graphql.generated.OwnershipType; import com.linkedin.datahub.graphql.generated.ResourceRefInput; +import com.linkedin.entity.client.EntityClient; import com.linkedin.metadata.Constants; import com.linkedin.metadata.authorization.PoliciesConfig; import com.linkedin.metadata.entity.EntityService; @@ -195,7 +196,12 @@ private static void removeOwnersIfExists( } public static void validateAuthorizedToUpdateOwners( - @Nonnull QueryContext context, Urn resourceUrn) { + @Nonnull QueryContext context, Urn resourceUrn, EntityClient entityClient) { + + if (GlossaryUtils.canUpdateGlossaryEntity(resourceUrn, context, entityClient)) { + return; + } + final DisjunctivePrivilegeGroup orPrivilegeGroups = new DisjunctivePrivilegeGroup( ImmutableList.of( diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/BatchSetDomainResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/BatchSetDomainResolverTest.java index 1a9272c1335cf..82b40154e07d2 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/BatchSetDomainResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/domain/BatchSetDomainResolverTest.java @@ -16,6 +16,7 @@ import com.linkedin.datahub.graphql.resolvers.mutate.BatchSetDomainResolver; import com.linkedin.datahub.graphql.resolvers.mutate.MutationUtils; import com.linkedin.domain.Domains; +import com.linkedin.entity.client.EntityClient; import com.linkedin.events.metadata.ChangeType; import com.linkedin.metadata.Constants; import com.linkedin.metadata.entity.EntityService; @@ -40,6 +41,7 @@ public class BatchSetDomainResolverTest { @Test public void testGetSuccessNoExistingDomains() throws Exception { EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when( mockService.getAspect( @@ -67,7 +69,7 @@ public void testGetSuccessNoExistingDomains() throws Exception { Mockito.when(mockService.exists(any(), eq(Urn.createFromString(TEST_DOMAIN_2_URN)), eq(true))) .thenReturn(true); - BatchSetDomainResolver resolver = new BatchSetDomainResolver(mockService); + BatchSetDomainResolver resolver = new BatchSetDomainResolver(mockService, mockClient); // Execute resolver QueryContext mockContext = getMockAllowContext(); @@ -106,6 +108,7 @@ public void testGetSuccessExistingDomains() throws Exception { .setDomains(new UrnArray(ImmutableList.of(Urn.createFromString(TEST_DOMAIN_1_URN)))); EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when( mockService.getAspect( @@ -133,7 +136,7 @@ public void testGetSuccessExistingDomains() throws Exception { Mockito.when(mockService.exists(any(), eq(Urn.createFromString(TEST_DOMAIN_2_URN)), eq(true))) .thenReturn(true); - BatchSetDomainResolver resolver = new BatchSetDomainResolver(mockService); + BatchSetDomainResolver resolver = new BatchSetDomainResolver(mockService, mockClient); // Execute resolver QueryContext mockContext = getMockAllowContext(); @@ -177,6 +180,7 @@ public void testGetSuccessUnsetDomains() throws Exception { .setDomains(new UrnArray(ImmutableList.of(Urn.createFromString(TEST_DOMAIN_1_URN)))); EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when( mockService.getAspect( @@ -204,7 +208,7 @@ public void testGetSuccessUnsetDomains() throws Exception { Mockito.when(mockService.exists(any(), eq(Urn.createFromString(TEST_DOMAIN_2_URN)), eq(true))) .thenReturn(true); - BatchSetDomainResolver resolver = new BatchSetDomainResolver(mockService); + BatchSetDomainResolver resolver = new BatchSetDomainResolver(mockService, mockClient); // Execute resolver QueryContext mockContext = getMockAllowContext(); @@ -234,6 +238,7 @@ public void testGetSuccessUnsetDomains() throws Exception { @Test public void testGetFailureDomainDoesNotExist() throws Exception { EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when( mockService.getAspect( @@ -248,7 +253,7 @@ public void testGetFailureDomainDoesNotExist() throws Exception { Mockito.when(mockService.exists(any(), eq(Urn.createFromString(TEST_DOMAIN_1_URN)), eq(true))) .thenReturn(false); - BatchSetDomainResolver resolver = new BatchSetDomainResolver(mockService); + BatchSetDomainResolver resolver = new BatchSetDomainResolver(mockService, mockClient); // Execute resolver QueryContext mockContext = getMockAllowContext(); @@ -269,6 +274,7 @@ public void testGetFailureDomainDoesNotExist() throws Exception { @Test public void testGetFailureResourceDoesNotExist() throws Exception { EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when( mockService.getAspect( @@ -292,7 +298,7 @@ public void testGetFailureResourceDoesNotExist() throws Exception { Mockito.when(mockService.exists(any(), eq(Urn.createFromString(TEST_DOMAIN_1_URN)), eq(true))) .thenReturn(true); - BatchSetDomainResolver resolver = new BatchSetDomainResolver(mockService); + BatchSetDomainResolver resolver = new BatchSetDomainResolver(mockService, mockClient); // Execute resolver QueryContext mockContext = getMockAllowContext(); @@ -313,8 +319,9 @@ public void testGetFailureResourceDoesNotExist() throws Exception { @Test public void testGetUnauthorized() throws Exception { EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); - BatchSetDomainResolver resolver = new BatchSetDomainResolver(mockService); + BatchSetDomainResolver resolver = new BatchSetDomainResolver(mockService, mockClient); // Execute resolver DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); @@ -335,12 +342,13 @@ public void testGetUnauthorized() throws Exception { @Test public void testGetEntityClientException() throws Exception { EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.doThrow(RuntimeException.class) .when(mockService) .ingestProposal(any(), Mockito.any(AspectsBatchImpl.class), Mockito.anyBoolean()); - BatchSetDomainResolver resolver = new BatchSetDomainResolver(mockService); + BatchSetDomainResolver resolver = new BatchSetDomainResolver(mockService, mockClient); // Execute resolver DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/AddOwnersResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/AddOwnersResolverTest.java index b239e0300ffcc..3222cc8c1878f 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/AddOwnersResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/AddOwnersResolverTest.java @@ -20,6 +20,7 @@ import com.linkedin.datahub.graphql.generated.OwnershipType; import com.linkedin.datahub.graphql.resolvers.mutate.AddOwnersResolver; import com.linkedin.datahub.graphql.resolvers.mutate.util.OwnerUtils; +import com.linkedin.entity.client.EntityClient; import com.linkedin.metadata.Constants; import com.linkedin.metadata.entity.EntityService; import com.linkedin.metadata.entity.ebean.batch.AspectsBatchImpl; @@ -39,6 +40,7 @@ public class AddOwnersResolverTest { @Test public void testGetSuccessNoExistingOwners() throws Exception { EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when( mockService.getAspect( @@ -66,7 +68,7 @@ public void testGetSuccessNoExistingOwners() throws Exception { eq(true))) .thenReturn(true); - AddOwnersResolver resolver = new AddOwnersResolver(mockService); + AddOwnersResolver resolver = new AddOwnersResolver(mockService, mockClient); // Execute resolver QueryContext mockContext = getMockAllowContext(); @@ -102,6 +104,7 @@ public void testGetSuccessNoExistingOwners() throws Exception { @Test public void testGetSuccessExistingOwnerNewType() throws Exception { EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); com.linkedin.common.Ownership oldOwnership = new Ownership() @@ -138,7 +141,7 @@ public void testGetSuccessExistingOwnerNewType() throws Exception { eq(true))) .thenReturn(true); - AddOwnersResolver resolver = new AddOwnersResolver(mockService); + AddOwnersResolver resolver = new AddOwnersResolver(mockService, mockClient); // Execute resolver QueryContext mockContext = getMockAllowContext(); @@ -168,6 +171,7 @@ public void testGetSuccessExistingOwnerNewType() throws Exception { @Test public void testGetSuccessDeprecatedTypeToOwnershipType() throws Exception { EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); com.linkedin.common.Ownership oldOwnership = new Ownership() @@ -201,7 +205,7 @@ public void testGetSuccessDeprecatedTypeToOwnershipType() throws Exception { eq(true))) .thenReturn(true); - AddOwnersResolver resolver = new AddOwnersResolver(mockService); + AddOwnersResolver resolver = new AddOwnersResolver(mockService, mockClient); // Execute resolver QueryContext mockContext = getMockAllowContext(); @@ -231,6 +235,7 @@ public void testGetSuccessDeprecatedTypeToOwnershipType() throws Exception { @Test public void testGetSuccessMultipleOwnerTypes() throws Exception { EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); com.linkedin.common.Ownership oldOwnership = new Ownership() @@ -281,7 +286,7 @@ public void testGetSuccessMultipleOwnerTypes() throws Exception { eq(true))) .thenReturn(true); - AddOwnersResolver resolver = new AddOwnersResolver(mockService); + AddOwnersResolver resolver = new AddOwnersResolver(mockService, mockClient); // Execute resolver QueryContext mockContext = getMockAllowContext(); @@ -329,6 +334,7 @@ public void testGetSuccessMultipleOwnerTypes() throws Exception { @Test public void testGetFailureOwnerDoesNotExist() throws Exception { EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when( mockService.getAspect( @@ -343,7 +349,7 @@ public void testGetFailureOwnerDoesNotExist() throws Exception { Mockito.when(mockService.exists(any(), eq(Urn.createFromString(TEST_OWNER_1_URN)), eq(true))) .thenReturn(false); - AddOwnersResolver resolver = new AddOwnersResolver(mockService); + AddOwnersResolver resolver = new AddOwnersResolver(mockService, mockClient); // Execute resolver QueryContext mockContext = getMockAllowContext(); @@ -367,6 +373,7 @@ public void testGetFailureOwnerDoesNotExist() throws Exception { @Test public void testGetFailureResourceDoesNotExist() throws Exception { EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when( mockService.getAspect( @@ -381,7 +388,7 @@ public void testGetFailureResourceDoesNotExist() throws Exception { Mockito.when(mockService.exists(any(), eq(Urn.createFromString(TEST_OWNER_1_URN)), eq(true))) .thenReturn(true); - AddOwnersResolver resolver = new AddOwnersResolver(mockService); + AddOwnersResolver resolver = new AddOwnersResolver(mockService, mockClient); // Execute resolver QueryContext mockContext = getMockAllowContext(); @@ -405,8 +412,9 @@ public void testGetFailureResourceDoesNotExist() throws Exception { @Test public void testGetUnauthorized() throws Exception { EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); - AddOwnersResolver resolver = new AddOwnersResolver(mockService); + AddOwnersResolver resolver = new AddOwnersResolver(mockService, mockClient); // Execute resolver DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); @@ -430,12 +438,14 @@ public void testGetUnauthorized() throws Exception { @Test public void testGetEntityClientException() throws Exception { EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.doThrow(RuntimeException.class) .when(mockService) .ingestProposal(any(), any(AspectsBatchImpl.class), Mockito.anyBoolean()); - AddOwnersResolver resolver = new AddOwnersResolver(Mockito.mock(EntityService.class)); + AddOwnersResolver resolver = + new AddOwnersResolver(Mockito.mock(EntityService.class), mockClient); // Execute resolver DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/BatchAddOwnersResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/BatchAddOwnersResolverTest.java index 8275f9f83ef83..2071b01c10558 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/BatchAddOwnersResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/BatchAddOwnersResolverTest.java @@ -19,6 +19,7 @@ import com.linkedin.datahub.graphql.generated.ResourceRefInput; import com.linkedin.datahub.graphql.resolvers.mutate.BatchAddOwnersResolver; import com.linkedin.datahub.graphql.resolvers.mutate.util.OwnerUtils; +import com.linkedin.entity.client.EntityClient; import com.linkedin.metadata.Constants; import com.linkedin.metadata.entity.EntityService; import com.linkedin.metadata.entity.ebean.batch.AspectsBatchImpl; @@ -39,6 +40,7 @@ public class BatchAddOwnersResolverTest { @Test public void testGetSuccessNoExistingOwners() throws Exception { EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when( mockService.getAspect( @@ -77,7 +79,7 @@ public void testGetSuccessNoExistingOwners() throws Exception { eq(true))) .thenReturn(true); - BatchAddOwnersResolver resolver = new BatchAddOwnersResolver(mockService); + BatchAddOwnersResolver resolver = new BatchAddOwnersResolver(mockService, mockClient); // Execute resolver QueryContext mockContext = getMockAllowContext(); @@ -127,6 +129,7 @@ public void testGetSuccessExistingOwners() throws Exception { .setOwner(Urn.createFromString(TEST_OWNER_URN_1)) .setType(OwnershipType.TECHNICAL_OWNER)))); EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when( mockService.getAspect( @@ -176,7 +179,7 @@ public void testGetSuccessExistingOwners() throws Exception { eq(true))) .thenReturn(true); - BatchAddOwnersResolver resolver = new BatchAddOwnersResolver(mockService); + BatchAddOwnersResolver resolver = new BatchAddOwnersResolver(mockService, mockClient); // Execute resolver QueryContext mockContext = getMockAllowContext(); @@ -218,6 +221,7 @@ public void testGetSuccessExistingOwners() throws Exception { @Test public void testGetFailureOwnerDoesNotExist() throws Exception { EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when( mockService.getAspect( @@ -232,7 +236,7 @@ public void testGetFailureOwnerDoesNotExist() throws Exception { Mockito.when(mockService.exists(any(), eq(Urn.createFromString(TEST_OWNER_URN_1)), eq(true))) .thenReturn(false); - BatchAddOwnersResolver resolver = new BatchAddOwnersResolver(mockService); + BatchAddOwnersResolver resolver = new BatchAddOwnersResolver(mockService, mockClient); // Execute resolver QueryContext mockContext = getMockAllowContext(); @@ -268,6 +272,7 @@ public void testGetFailureOwnerDoesNotExist() throws Exception { @Test public void testGetFailureResourceDoesNotExist() throws Exception { EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when( mockService.getAspect( @@ -291,7 +296,7 @@ public void testGetFailureResourceDoesNotExist() throws Exception { Mockito.when(mockService.exists(any(), eq(Urn.createFromString(TEST_OWNER_URN_1)), eq(true))) .thenReturn(true); - BatchAddOwnersResolver resolver = new BatchAddOwnersResolver(mockService); + BatchAddOwnersResolver resolver = new BatchAddOwnersResolver(mockService, mockClient); // Execute resolver QueryContext mockContext = getMockAllowContext(); @@ -327,8 +332,9 @@ public void testGetFailureResourceDoesNotExist() throws Exception { @Test public void testGetUnauthorized() throws Exception { EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); - BatchAddOwnersResolver resolver = new BatchAddOwnersResolver(mockService); + BatchAddOwnersResolver resolver = new BatchAddOwnersResolver(mockService, mockClient); // Execute resolver DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); @@ -364,12 +370,13 @@ public void testGetUnauthorized() throws Exception { @Test public void testGetEntityClientException() throws Exception { EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.doThrow(RuntimeException.class) .when(mockService) .ingestProposal(any(), Mockito.any(AspectsBatchImpl.class), Mockito.anyBoolean()); - BatchAddOwnersResolver resolver = new BatchAddOwnersResolver(mockService); + BatchAddOwnersResolver resolver = new BatchAddOwnersResolver(mockService, mockClient); // Execute resolver DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/BatchRemoveOwnersResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/BatchRemoveOwnersResolverTest.java index 9ea9ac693b98e..24380e2e52d84 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/BatchRemoveOwnersResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/owner/BatchRemoveOwnersResolverTest.java @@ -16,6 +16,7 @@ import com.linkedin.datahub.graphql.generated.BatchRemoveOwnersInput; import com.linkedin.datahub.graphql.generated.ResourceRefInput; import com.linkedin.datahub.graphql.resolvers.mutate.BatchRemoveOwnersResolver; +import com.linkedin.entity.client.EntityClient; import com.linkedin.metadata.Constants; import com.linkedin.metadata.entity.EntityService; import com.linkedin.metadata.entity.ebean.batch.AspectsBatchImpl; @@ -36,6 +37,7 @@ public class BatchRemoveOwnersResolverTest { @Test public void testGetSuccessNoExistingOwners() throws Exception { EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when( mockService.getAspect( @@ -62,7 +64,7 @@ public void testGetSuccessNoExistingOwners() throws Exception { Mockito.when(mockService.exists(any(), eq(Urn.createFromString(TEST_OWNER_URN_2)), eq(true))) .thenReturn(true); - BatchRemoveOwnersResolver resolver = new BatchRemoveOwnersResolver(mockService); + BatchRemoveOwnersResolver resolver = new BatchRemoveOwnersResolver(mockService, mockClient); // Execute resolver QueryContext mockContext = getMockAllowContext(); @@ -84,6 +86,7 @@ public void testGetSuccessNoExistingOwners() throws Exception { @Test public void testGetSuccessExistingOwners() throws Exception { EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); final Ownership oldOwners1 = new Ownership() @@ -129,7 +132,7 @@ public void testGetSuccessExistingOwners() throws Exception { Mockito.when(mockService.exists(any(), eq(Urn.createFromString(TEST_OWNER_URN_2)), eq(true))) .thenReturn(true); - BatchRemoveOwnersResolver resolver = new BatchRemoveOwnersResolver(mockService); + BatchRemoveOwnersResolver resolver = new BatchRemoveOwnersResolver(mockService, mockClient); // Execute resolver QueryContext mockContext = getMockAllowContext(); @@ -151,6 +154,7 @@ public void testGetSuccessExistingOwners() throws Exception { @Test public void testGetFailureResourceDoesNotExist() throws Exception { EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.when( mockService.getAspect( @@ -174,7 +178,7 @@ public void testGetFailureResourceDoesNotExist() throws Exception { Mockito.when(mockService.exists(any(), eq(Urn.createFromString(TEST_OWNER_URN_1)), eq(true))) .thenReturn(true); - BatchRemoveOwnersResolver resolver = new BatchRemoveOwnersResolver(mockService); + BatchRemoveOwnersResolver resolver = new BatchRemoveOwnersResolver(mockService, mockClient); // Execute resolver QueryContext mockContext = getMockAllowContext(); @@ -196,8 +200,9 @@ public void testGetFailureResourceDoesNotExist() throws Exception { @Test public void testGetUnauthorized() throws Exception { EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); - BatchRemoveOwnersResolver resolver = new BatchRemoveOwnersResolver(mockService); + BatchRemoveOwnersResolver resolver = new BatchRemoveOwnersResolver(mockService, mockClient); // Execute resolver DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class); @@ -219,12 +224,13 @@ public void testGetUnauthorized() throws Exception { @Test public void testGetEntityClientException() throws Exception { EntityService mockService = getMockEntityService(); + EntityClient mockClient = Mockito.mock(EntityClient.class); Mockito.doThrow(RuntimeException.class) .when(mockService) .ingestProposal(any(), Mockito.any(AspectsBatchImpl.class), Mockito.anyBoolean()); - BatchRemoveOwnersResolver resolver = new BatchRemoveOwnersResolver(mockService); + BatchRemoveOwnersResolver resolver = new BatchRemoveOwnersResolver(mockService, mockClient); // Execute resolver DataFetchingEnvironment mockEnv = Mockito.mock(DataFetchingEnvironment.class);