Skip to content
Open
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 @@ -4,6 +4,7 @@
import static com.linkedin.datahub.graphql.resolvers.mutate.MutationUtils.*;
import static com.linkedin.metadata.Constants.*;

import com.google.common.collect.ImmutableList;
import com.linkedin.common.AuditStamp;
import com.linkedin.common.urn.Urn;
import com.linkedin.common.urn.UrnUtils;
Expand All @@ -15,7 +16,7 @@
import com.linkedin.datahub.graphql.exception.DataHubGraphQLErrorCode;
import com.linkedin.datahub.graphql.exception.DataHubGraphQLException;
import com.linkedin.datahub.graphql.generated.CreateDomainInput;
import com.linkedin.datahub.graphql.generated.OwnerEntityType;
import com.linkedin.datahub.graphql.generated.ResourceRefInput;
import com.linkedin.datahub.graphql.resolvers.mutate.util.DomainUtils;
import com.linkedin.datahub.graphql.resolvers.mutate.util.OwnerUtils;
import com.linkedin.domain.DomainProperties;
Expand Down Expand Up @@ -99,8 +100,20 @@ public CompletableFuture<String> get(DataFetchingEnvironment environment) throws

String domainUrn =
_entityClient.ingestProposal(context.getOperationContext(), proposal, false);
OwnerUtils.addCreatorAsOwner(
context, domainUrn, OwnerEntityType.CORP_USER, _entityService);

if (input.getOwners() != null && !input.getOwners().isEmpty()) {
input.getOwners().stream()
.forEach(
(ownerInput) ->
OwnerUtils.validateOwner(
context.getOperationContext(), ownerInput, _entityService));
OwnerUtils.addOwnersToResources(
context.getOperationContext(),
input.getOwners(),
ImmutableList.of(new ResourceRefInput(domainUrn, null, null)),
UrnUtils.getUrn(context.getActorUrn()),
_entityService);
}
return domainUrn;
} catch (DataHubGraphQLException e) {
throw e;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import com.linkedin.datahub.graphql.concurrency.GraphQLConcurrencyUtils;
import com.linkedin.datahub.graphql.exception.AuthorizationException;
import com.linkedin.datahub.graphql.generated.CreateGlossaryEntityInput;
import com.linkedin.datahub.graphql.generated.OwnerEntityType;
import com.linkedin.datahub.graphql.resolvers.mutate.util.GlossaryUtils;
import com.linkedin.datahub.graphql.resolvers.mutate.util.OwnerUtils;
import com.linkedin.entity.client.EntityClient;
Expand Down Expand Up @@ -70,8 +69,13 @@ public CompletableFuture<String> get(DataFetchingEnvironment environment) throws
String glossaryNodeUrn =
_entityClient.ingestProposal(context.getOperationContext(), proposal, false);

OwnerUtils.addCreatorAsOwner(
context, glossaryNodeUrn, OwnerEntityType.CORP_USER, _entityService);
OwnerUtils.validateAndAddOwnersOnEntityCreation(
context.getOperationContext(),
input.getOwners(),
glossaryNodeUrn,
UrnUtils.getUrn(context.getActorUrn()),
_entityService);

return glossaryNodeUrn;
} catch (Exception e) {
log.error(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import com.linkedin.datahub.graphql.concurrency.GraphQLConcurrencyUtils;
import com.linkedin.datahub.graphql.exception.AuthorizationException;
import com.linkedin.datahub.graphql.generated.CreateGlossaryEntityInput;
import com.linkedin.datahub.graphql.generated.OwnerEntityType;
import com.linkedin.datahub.graphql.resolvers.mutate.util.GlossaryUtils;
import com.linkedin.datahub.graphql.resolvers.mutate.util.OwnerUtils;
import com.linkedin.entity.EntityResponse;
Expand Down Expand Up @@ -88,8 +87,13 @@ public CompletableFuture<String> get(DataFetchingEnvironment environment) throws
String glossaryTermUrn =
_entityClient.ingestProposal(context.getOperationContext(), proposal, false);

OwnerUtils.addCreatorAsOwner(
context, glossaryTermUrn, OwnerEntityType.CORP_USER, _entityService);
OwnerUtils.validateAndAddOwnersOnEntityCreation(
context.getOperationContext(),
input.getOwners(),
glossaryTermUrn,
UrnUtils.getUrn(context.getActorUrn()),
_entityService);

return glossaryTermUrn;
} catch (Exception e) {
log.error(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,15 @@ static MetadataChangeProposal buildAddOwnersProposal(
input.getType() != null
? OwnershipType.valueOf(input.getType().toString())
: OwnershipType.NONE;
final Urn ownershipTypeUrn =
input.getOwnershipTypeUrn() != null
? UrnUtils.getUrn(input.getOwnershipTypeUrn())
: UrnUtils.getUrn(mapOwnershipTypeToEntity(ownershipType.name()));
OwnerServiceUtils.addOwnerToAspect(
ownershipAspect,
UrnUtils.getUrn(input.getOwnerUrn()),
com.linkedin.common.OwnershipType.valueOf(ownershipType.toString()),
UrnUtils.getUrn(input.getOwnershipTypeUrn()),
ownershipTypeUrn,
OwnershipSourceType.MANUAL);
}
return buildMetadataChangeProposalWithUrn(
Expand Down Expand Up @@ -300,4 +304,35 @@ public static boolean isAuthorizedToUpdateOwners(@Nonnull QueryContext context,
return AuthorizationUtils.isAuthorized(
context, resourceUrn.getEntityType(), resourceUrn.toString(), orPrivilegeGroups);
}

/**
* Validates and adds owners to a newly created entity if owners are provided. This is a
* convenience method that combines validation and owner assignment for use in entity creation
* resolvers.
*
* @param opContext The operation context
* @param ownerInputs List of owner inputs to validate and add (can be null or empty)
* @param resourceUrn URN of the resource to add owners to
* @param actorUrn URN of the actor performing the operation
* @param entityService Entity service for validation and persistence
*/
public static void validateAndAddOwnersOnEntityCreation(
@Nonnull OperationContext opContext,
@Nullable List<OwnerInput> ownerInputs,
@Nonnull String resourceUrn,
@Nonnull Urn actorUrn,
@Nonnull EntityService<?> entityService) {
if (ownerInputs != null && !ownerInputs.isEmpty()) {
// Validate all owner inputs
ownerInputs.forEach(ownerInput -> validateOwner(opContext, ownerInput, entityService));

// Add validated owners to the resource
addOwnersToResources(
opContext,
ownerInputs,
ImmutableList.of(new ResourceRefInput(resourceUrn, null, null)),
actorUrn,
entityService);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
import static com.linkedin.datahub.graphql.resolvers.mutate.MutationUtils.*;
import static com.linkedin.metadata.Constants.*;

import com.linkedin.common.urn.UrnUtils;
import com.linkedin.data.template.SetMode;
import com.linkedin.datahub.graphql.QueryContext;
import com.linkedin.datahub.graphql.authorization.AuthorizationUtils;
import com.linkedin.datahub.graphql.concurrency.GraphQLConcurrencyUtils;
import com.linkedin.datahub.graphql.exception.AuthorizationException;
import com.linkedin.datahub.graphql.generated.CreateTagInput;
import com.linkedin.datahub.graphql.generated.OwnerEntityType;
import com.linkedin.datahub.graphql.resolvers.mutate.util.OwnerUtils;
import com.linkedin.entity.client.EntityClient;
import com.linkedin.metadata.entity.EntityService;
Expand Down Expand Up @@ -71,8 +71,13 @@ public CompletableFuture<String> get(DataFetchingEnvironment environment) throws
String tagUrn =
_entityClient.ingestProposal(context.getOperationContext(), proposal, false);

OwnerUtils.addCreatorAsOwner(
context, tagUrn, OwnerEntityType.CORP_USER, _entityService);
OwnerUtils.validateAndAddOwnersOnEntityCreation(
context.getOperationContext(),
input.getOwners(),
tagUrn,
UrnUtils.getUrn(context.getActorUrn()),
_entityService);

return tagUrn;
} catch (Exception e) {
log.error(
Expand Down
18 changes: 18 additions & 0 deletions datahub-graphql-core/src/main/resources/entity.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -5415,6 +5415,12 @@ input CreateTagInput {
Optional description for the Tag
"""
description: String

"""
Optional - Add owners to the tag.
If not provided, no owner will be assigned.
"""
owners: [OwnerInput!]
}

"""
Expand Down Expand Up @@ -11567,6 +11573,12 @@ input CreateDomainInput {
Optional parent domain urn for the domain
"""
parentDomain: String

"""
Optional - Add owners to the domain.
If not provided, we'll automatically assign the current actor as the owner.
"""
owners: [OwnerInput!]
}

"""
Expand Down Expand Up @@ -11707,6 +11719,12 @@ input CreateGlossaryEntityInput {
Optional parent node urn for the Glossary Node or Term
"""
parentNode: String

"""
Optional - Add owners to the glossary term or node.
If not provided, no owner will be assigned.
"""
owners: [OwnerInput!]
}

enum HealthStatus {
Expand Down
Loading