Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(properties) Add upsertStructuredProperties graphql endpoint for assets #9906

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 @@ -257,6 +257,7 @@
import com.linkedin.datahub.graphql.resolvers.settings.view.UpdateGlobalViewsSettingsResolver;
import com.linkedin.datahub.graphql.resolvers.step.BatchGetStepStatesResolver;
import com.linkedin.datahub.graphql.resolvers.step.BatchUpdateStepStatesResolver;
import com.linkedin.datahub.graphql.resolvers.structuredproperties.UpsertStructuredPropertiesResolver;
import com.linkedin.datahub.graphql.resolvers.tag.CreateTagResolver;
import com.linkedin.datahub.graphql.resolvers.tag.DeleteTagResolver;
import com.linkedin.datahub.graphql.resolvers.tag.SetTagColorResolver;
Expand Down Expand Up @@ -844,6 +845,7 @@ private void configureContainerResolvers(final RuntimeWiring.Builder builder) {
typeWiring
.dataFetcher("relationships", new EntityRelationshipsResultResolver(graphClient))
.dataFetcher("entities", new ContainerEntitiesResolver(entityClient))
.dataFetcher("privileges", new EntityPrivilegesResolver(entityClient))
.dataFetcher(
"aspects", new WeaklyTypedAspectsResolver(entityClient, entityRegistry))
.dataFetcher("exists", new EntityExistsResolver(entityService))
Expand Down Expand Up @@ -1243,6 +1245,9 @@ private void configureMutationResolvers(final RuntimeWiring.Builder builder) {
.dataFetcher(
"verifyForm", new VerifyFormResolver(this.formService, this.groupService))
.dataFetcher("batchRemoveForm", new BatchRemoveFormResolver(this.formService))
.dataFetcher(
"upsertStructuredProperties",
new UpsertStructuredPropertiesResolver(this.entityClient))
.dataFetcher("raiseIncident", new RaiseIncidentResolver(this.entityClient))
.dataFetcher(
"updateIncidentStatus",
Expand Down Expand Up @@ -1719,6 +1724,7 @@ private void configureCorpUserResolvers(final RuntimeWiring.Builder builder) {
typeWiring ->
typeWiring
.dataFetcher("relationships", new EntityRelationshipsResultResolver(graphClient))
.dataFetcher("privileges", new EntityPrivilegesResolver(entityClient))
.dataFetcher(
"aspects", new WeaklyTypedAspectsResolver(entityClient, entityRegistry)));
builder.type(
Expand All @@ -1741,6 +1747,7 @@ private void configureCorpGroupResolvers(final RuntimeWiring.Builder builder) {
typeWiring ->
typeWiring
.dataFetcher("relationships", new EntityRelationshipsResultResolver(graphClient))
.dataFetcher("privileges", new EntityPrivilegesResolver(entityClient))
.dataFetcher(
"aspects", new WeaklyTypedAspectsResolver(entityClient, entityRegistry))
.dataFetcher("exists", new EntityExistsResolver(entityService)));
Expand Down Expand Up @@ -2253,6 +2260,7 @@ private void configureDataFlowResolvers(final RuntimeWiring.Builder builder) {
dataPlatformType,
(env) -> ((DataFlow) env.getSource()).getPlatform().getUrn()))
.dataFetcher("exists", new EntityExistsResolver(entityService))
.dataFetcher("privileges", new EntityPrivilegesResolver(entityClient))
.dataFetcher(
"dataPlatformInstance",
new LoadableTypeResolver<>(
Expand Down Expand Up @@ -2300,6 +2308,7 @@ private void configureMLFeatureTableResolvers(final RuntimeWiring.Builder builde
new LoadableTypeResolver<>(
dataPlatformType,
(env) -> ((MLFeatureTable) env.getSource()).getPlatform().getUrn()))
.dataFetcher("privileges", new EntityPrivilegesResolver(entityClient))
.dataFetcher(
"dataPlatformInstance",
new LoadableTypeResolver<>(
Expand Down Expand Up @@ -2390,6 +2399,7 @@ private void configureMLFeatureTableResolvers(final RuntimeWiring.Builder builde
new LoadableTypeResolver<>(
dataPlatformType,
(env) -> ((MLModel) env.getSource()).getPlatform().getUrn()))
.dataFetcher("privileges", new EntityPrivilegesResolver(entityClient))
.dataFetcher(
"dataPlatformInstance",
new LoadableTypeResolver<>(
Expand Down Expand Up @@ -2438,6 +2448,7 @@ private void configureMLFeatureTableResolvers(final RuntimeWiring.Builder builde
dataPlatformType,
(env) -> ((MLModelGroup) env.getSource()).getPlatform().getUrn()))
.dataFetcher("exists", new EntityExistsResolver(entityService))
.dataFetcher("privileges", new EntityPrivilegesResolver(entityClient))
.dataFetcher(
"dataPlatformInstance",
new LoadableTypeResolver<>(
Expand All @@ -2463,6 +2474,7 @@ private void configureMLFeatureTableResolvers(final RuntimeWiring.Builder builde
.dataFetcher(
"aspects", new WeaklyTypedAspectsResolver(entityClient, entityRegistry))
.dataFetcher("exists", new EntityExistsResolver(entityService))
.dataFetcher("privileges", new EntityPrivilegesResolver(entityClient))
.dataFetcher(
"dataPlatformInstance",
new LoadableTypeResolver<>(
Expand All @@ -2479,6 +2491,7 @@ private void configureMLFeatureTableResolvers(final RuntimeWiring.Builder builde
typeWiring
.dataFetcher(
"relationships", new EntityRelationshipsResultResolver(graphClient))
.dataFetcher("privileges", new EntityPrivilegesResolver(entityClient))
.dataFetcher(
"lineage",
new EntityLineageResultResolver(
Expand Down Expand Up @@ -2521,6 +2534,7 @@ private void configureDomainResolvers(final RuntimeWiring.Builder builder) {
typeWiring
.dataFetcher("entities", new DomainEntitiesResolver(this.entityClient))
.dataFetcher("parentDomains", new ParentDomainsResolver(this.entityClient))
.dataFetcher("privileges", new EntityPrivilegesResolver(entityClient))
.dataFetcher(
"aspects", new WeaklyTypedAspectsResolver(entityClient, entityRegistry))
.dataFetcher("relationships", new EntityRelationshipsResultResolver(graphClient)));
Expand Down Expand Up @@ -2593,6 +2607,7 @@ private void configureDataProductResolvers(final RuntimeWiring.Builder builder)
typeWiring ->
typeWiring
.dataFetcher("entities", new ListDataProductAssetsResolver(this.entityClient))
.dataFetcher("privileges", new EntityPrivilegesResolver(entityClient))
.dataFetcher(
"aspects", new WeaklyTypedAspectsResolver(entityClient, entityRegistry))
.dataFetcher("relationships", new EntityRelationshipsResultResolver(graphClient)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,24 @@ public static boolean canManageOwnershipTypes(@Nonnull QueryContext context) {
return isAuthorized(context, Optional.empty(), PoliciesConfig.MANAGE_GLOBAL_OWNERSHIP_TYPES);
}

public static boolean canEditProperties(@Nonnull Urn targetUrn, @Nonnull QueryContext context) {
// If you either have all entity privileges, or have the specific privileges required, you are
// authorized.
final DisjunctivePrivilegeGroup orPrivilegeGroups =
new DisjunctivePrivilegeGroup(
ImmutableList.of(
ALL_PRIVILEGES_GROUP,
new ConjunctivePrivilegeGroup(
ImmutableList.of(PoliciesConfig.EDIT_ENTITY_PROPERTIES_PRIVILEGE.getType()))));

return AuthorizationUtils.isAuthorized(
context.getAuthorizer(),
context.getActorUrn(),
targetUrn.getEntityType(),
targetUrn.toString(),
orPrivilegeGroups);
}

public static boolean canEditEntityQueries(
@Nonnull List<Urn> entityUrns, @Nonnull QueryContext context) {
final DisjunctivePrivilegeGroup orPrivilegeGroups =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import graphql.schema.DataFetchingEnvironment;
import java.util.Collections;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Nonnull;
import lombok.extern.slf4j.Slf4j;

@Slf4j
Expand Down Expand Up @@ -52,15 +53,18 @@ public CompletableFuture<EntityPrivileges> get(DataFetchingEnvironment environme
return getDataJobPrivileges(urn, context);
default:
log.warn(
"Tried to get entity privileges for entity type {} but nothing is implemented for it yet",
"Tried to get entity privileges for entity type {}. Adding common privileges only.",
urn.getEntityType());
return new EntityPrivileges();
EntityPrivileges commonPrivileges = new EntityPrivileges();
addCommonPrivileges(commonPrivileges, urn, context);
return commonPrivileges;
}
});
}

private EntityPrivileges getGlossaryTermPrivileges(Urn termUrn, QueryContext context) {
final EntityPrivileges result = new EntityPrivileges();
addCommonPrivileges(result, termUrn, context);
result.setCanManageEntity(false);
if (GlossaryUtils.canManageGlossaries(context)) {
result.setCanManageEntity(true);
Expand All @@ -77,6 +81,7 @@ private EntityPrivileges getGlossaryTermPrivileges(Urn termUrn, QueryContext con

private EntityPrivileges getGlossaryNodePrivileges(Urn nodeUrn, QueryContext context) {
final EntityPrivileges result = new EntityPrivileges();
addCommonPrivileges(result, nodeUrn, context);
result.setCanManageEntity(false);
if (GlossaryUtils.canManageGlossaries(context)) {
result.setCanManageEntity(true);
Expand Down Expand Up @@ -117,29 +122,35 @@ private boolean canEditEntityLineage(Urn urn, QueryContext context) {

private EntityPrivileges getDatasetPrivileges(Urn urn, QueryContext context) {
final EntityPrivileges result = new EntityPrivileges();
result.setCanEditLineage(canEditEntityLineage(urn, context));
result.setCanEditEmbed(EmbedUtils.isAuthorizedToUpdateEmbedForEntity(urn, context));
result.setCanEditQueries(AuthorizationUtils.canCreateQuery(ImmutableList.of(urn), context));
addCommonPrivileges(result, urn, context);
return result;
}

private EntityPrivileges getChartPrivileges(Urn urn, QueryContext context) {
final EntityPrivileges result = new EntityPrivileges();
result.setCanEditLineage(canEditEntityLineage(urn, context));
result.setCanEditEmbed(EmbedUtils.isAuthorizedToUpdateEmbedForEntity(urn, context));
addCommonPrivileges(result, urn, context);
return result;
}

private EntityPrivileges getDashboardPrivileges(Urn urn, QueryContext context) {
final EntityPrivileges result = new EntityPrivileges();
result.setCanEditLineage(canEditEntityLineage(urn, context));
result.setCanEditEmbed(EmbedUtils.isAuthorizedToUpdateEmbedForEntity(urn, context));
addCommonPrivileges(result, urn, context);
return result;
}

private EntityPrivileges getDataJobPrivileges(Urn urn, QueryContext context) {
final EntityPrivileges result = new EntityPrivileges();
result.setCanEditLineage(canEditEntityLineage(urn, context));
addCommonPrivileges(result, urn, context);
return result;
}

private void addCommonPrivileges(
@Nonnull EntityPrivileges result, @Nonnull Urn urn, @Nonnull QueryContext context) {
result.setCanEditLineage(canEditEntityLineage(urn, context));
result.setCanEditProperties(AuthorizationUtils.canEditProperties(urn, context));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import com.linkedin.metadata.query.filter.Criterion;
import com.linkedin.metadata.query.filter.CriterionArray;
import com.linkedin.metadata.query.filter.Filter;
import com.linkedin.structured.PrimitivePropertyValue;
import com.linkedin.structured.PrimitivePropertyValueArray;
import java.util.Objects;
import javax.annotation.Nonnull;
Expand All @@ -37,14 +36,7 @@ public static PrimitivePropertyValueArray getStructuredPropertyValuesFromInput(
input
.getStructuredPropertyParams()
.getValues()
.forEach(
value -> {
if (value.getStringValue() != null) {
values.add(PrimitivePropertyValue.create(value.getStringValue()));
} else if (value.getNumberValue() != null) {
values.add(PrimitivePropertyValue.create(value.getNumberValue().doubleValue()));
}
});
.forEach(value -> values.add(StructuredPropertyUtils.mapPropertyValueInput(value)));

return values;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.linkedin.datahub.graphql.resolvers.mutate.util;

import com.linkedin.datahub.graphql.generated.PropertyValueInput;
import com.linkedin.structured.PrimitivePropertyValue;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public class StructuredPropertyUtils {

private StructuredPropertyUtils() {}

@Nullable
public static PrimitivePropertyValue mapPropertyValueInput(
@Nonnull final PropertyValueInput valueInput) {
if (valueInput.getStringValue() != null) {
return PrimitivePropertyValue.create(valueInput.getStringValue());
} else if (valueInput.getNumberValue() != null) {
return PrimitivePropertyValue.create(valueInput.getNumberValue().doubleValue());
}
return null;
}
}
Loading
Loading