fix(privileges) Use glossary term manage children privileges for edit docs and links (#7985)

This commit is contained in:
Chris Collins 2023-05-09 04:16:05 -04:00 committed by GitHub
parent b04d59e13d
commit 94e7e51175
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 40 additions and 10 deletions

View File

@ -819,13 +819,13 @@ public class GmsGraphQLEngine {
.dataFetcher("createPolicy", new UpsertPolicyResolver(this.entityClient))
.dataFetcher("updatePolicy", new UpsertPolicyResolver(this.entityClient))
.dataFetcher("deletePolicy", new DeletePolicyResolver(this.entityClient))
.dataFetcher("updateDescription", new UpdateDescriptionResolver(entityService))
.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("addLink", new AddLinkResolver(entityService))
.dataFetcher("addLink", new AddLinkResolver(entityService, this.entityClient))
.dataFetcher("removeLink", new RemoveLinkResolver(entityService))
.dataFetcher("addGroupMembers", new AddGroupMembersResolver(this.groupService))
.dataFetcher("removeGroupMembers", new RemoveGroupMembersResolver(this.groupService))

View File

@ -6,7 +6,10 @@ import com.linkedin.common.urn.Urn;
import com.linkedin.datahub.graphql.QueryContext;
import com.linkedin.datahub.graphql.exception.AuthorizationException;
import com.linkedin.datahub.graphql.generated.AddLinkInput;
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;
@ -22,6 +25,7 @@ import static com.linkedin.datahub.graphql.resolvers.ResolverUtils.*;
public class AddLinkResolver implements DataFetcher<CompletableFuture<Boolean>> {
private final EntityService _entityService;
private final EntityClient _entityClient;
@Override
public CompletableFuture<Boolean> get(DataFetchingEnvironment environment) throws Exception {
@ -31,7 +35,7 @@ public class AddLinkResolver implements DataFetcher<CompletableFuture<Boolean>>
String linkLabel = input.getLabel();
Urn targetUrn = Urn.createFromString(input.getResourceUrn());
if (!LinkUtils.isAuthorizedToUpdateLinks(environment.getContext(), targetUrn)) {
if (!LinkUtils.isAuthorizedToUpdateLinks(environment.getContext(), targetUrn) && !canUpdateGlossaryEntityLinks(targetUrn, environment.getContext())) {
throw new AuthorizationException("Unauthorized to perform this action. Please contact your DataHub administrator.");
}
@ -60,4 +64,16 @@ public class AddLinkResolver implements DataFetcher<CompletableFuture<Boolean>>
}
});
}
// 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);
}
}

View File

@ -5,7 +5,9 @@ import com.linkedin.common.urn.Urn;
import com.linkedin.datahub.graphql.QueryContext;
import com.linkedin.datahub.graphql.exception.AuthorizationException;
import com.linkedin.datahub.graphql.generated.DescriptionUpdateInput;
import com.linkedin.datahub.graphql.resolvers.mutate.util.GlossaryUtils;
import com.linkedin.datahub.graphql.resolvers.mutate.util.SiblingsUtils;
import com.linkedin.entity.client.EntityClient;
import com.linkedin.metadata.Constants;
import com.linkedin.metadata.entity.EntityService;
import graphql.schema.DataFetcher;
@ -27,6 +29,7 @@ import static com.linkedin.datahub.graphql.resolvers.ResolverUtils.*;
@RequiredArgsConstructor
public class UpdateDescriptionResolver implements DataFetcher<CompletableFuture<Boolean>> {
private final EntityService _entityService;
private final EntityClient _entityClient;
@Override
public CompletableFuture<Boolean> get(DataFetchingEnvironment environment) throws Exception {
@ -190,8 +193,10 @@ public class UpdateDescriptionResolver implements DataFetcher<CompletableFuture<
private CompletableFuture<Boolean> updateGlossaryTermDescription(Urn targetUrn, DescriptionUpdateInput input, QueryContext context) {
return CompletableFuture.supplyAsync(() -> {
if (!DescriptionUtils.isAuthorizedToUpdateDescription(context, targetUrn)) {
final Urn parentNodeUrn = GlossaryUtils.getParentUrn(targetUrn, context, _entityClient);
if (!DescriptionUtils.isAuthorizedToUpdateDescription(context, targetUrn)
&& !GlossaryUtils.canManageChildrenEntities(context, parentNodeUrn, _entityClient)
) {
throw new AuthorizationException(
"Unauthorized to perform this action. Please contact your DataHub administrator.");
}
@ -214,8 +219,10 @@ public class UpdateDescriptionResolver implements DataFetcher<CompletableFuture<
private CompletableFuture<Boolean> updateGlossaryNodeDescription(Urn targetUrn, DescriptionUpdateInput input, QueryContext context) {
return CompletableFuture.supplyAsync(() -> {
if (!DescriptionUtils.isAuthorizedToUpdateDescription(context, targetUrn)) {
final Urn parentNodeUrn = GlossaryUtils.getParentUrn(targetUrn, context, _entityClient);
if (!DescriptionUtils.isAuthorizedToUpdateDescription(context, targetUrn)
&& !GlossaryUtils.canManageChildrenEntities(context, parentNodeUrn, _entityClient)
) {
throw new AuthorizationException(
"Unauthorized to perform this action. Please contact your DataHub administrator.");
}

View File

@ -130,8 +130,8 @@ We currently support the following:
| Group | Edit Group Members | Allow actor to add and remove members to a group. |
| User | Edit User Profile | Allow actor to change the user's profile including display name, bio, title, profile image, etc. |
| User + Group | Edit Contact Information | Allow actor to change the contact information such as email & chat handles. |
| GlossaryNode | Manage Direct Glossary Children | Allow the actor to create and delete the direct children of the selected entities. |
| GlossaryNode | Manage All Glossary Children | Allow the actor to create and delete everything underneath the selected entities. |
| GlossaryNode | Manage Direct Glossary Children | Allow the actor to create, edit, and delete the direct children of the selected entities. |
| GlossaryNode | Manage All Glossary Children | Allow the actor to create, edit, and delete everything underneath the selected entities. |

View File

@ -85,6 +85,13 @@ In the modal that pops up you can select the Term you care about in one of two w
![](../imgs/glossary/add-term-modal.png)
## Privileges
Glossary Terms and Term Groups abide by metadata policies like other entities. However, there are two special privileges provided for configuring privileges within your Business Glossary.
- **Manage Direct Glossary Children**: If a user has this privilege on a Glossary Term Group, they will be able to create, edit, and delete Terms and Term Groups directly underneath the Term Group they have this privilege on.
- **Manage All Glossary Children**: If a user has this privilege on a Glossary Term Group, they will be able to create, edit, and delete any Term or Term Group anywhere underneath the Term Group they have this privilege on. This applies to the children of a child Term Group as well (and so on).
## Managing Glossary with Git
In many cases, it may be preferable to manage the Business Glossary in a version-control system like git. This can make