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 682710ad5d539..b03c929dd8436 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 @@ -1719,9 +1719,12 @@ private void configurePolicyResolvers(final RuntimeWiring.Builder builder) { })).dataFetcher("resolvedRoles", new LoadableTypeBatchResolver<>(dataHubRoleType, (env) -> { final ActorFilter filter = env.getSource(); return filter.getRoles(); - })).dataFetcher("resolvedOwnershipTypes", new LoadableTypeBatchResolver<>(ownershipType, (env) -> { + })).dataFetcher("resolvedResourceOwnershipTypes", new LoadableTypeBatchResolver<>(ownershipType, (env) -> { final ActorFilter filter = env.getSource(); return filter.getResourceOwnersTypes(); + })).dataFetcher("resolvedPlatformInstanceOwnershipTypes", new LoadableTypeBatchResolver<>(ownershipType, (env) -> { + final ActorFilter filter = env.getSource(); + return filter.getPlatformInstanceOwnersTypes(); }))); } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/policy/mappers/PolicyInfoPolicyMapper.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/policy/mappers/PolicyInfoPolicyMapper.java index b9a6bf07be8c8..2892607f349f1 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/policy/mappers/PolicyInfoPolicyMapper.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/policy/mappers/PolicyInfoPolicyMapper.java @@ -54,10 +54,15 @@ private ActorFilter mapActors(final DataHubActorFilter actorFilter) { result.setAllGroups(actorFilter.isAllGroups()); result.setAllUsers(actorFilter.isAllUsers()); result.setResourceOwners(actorFilter.isResourceOwners()); + result.setPlatformInstanceOwners(actorFilter.isPlatformInstanceOwners()); UrnArray resourceOwnersTypes = actorFilter.getResourceOwnersTypes(); if (resourceOwnersTypes != null) { result.setResourceOwnersTypes(resourceOwnersTypes.stream().map(Urn::toString).collect(Collectors.toList())); } + UrnArray platformInstanceOwnersTypes = actorFilter.getPlatformInstanceOwnersTypes(); + if (platformInstanceOwnersTypes != null) { + result.setPlatformInstanceOwnersTypes(platformInstanceOwnersTypes.stream().map(Urn::toString).collect(Collectors.toList())); + } if (actorFilter.hasGroups()) { result.setGroups(actorFilter.getGroups().stream().map(Urn::toString).collect(Collectors.toList())); } diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/policy/mappers/PolicyUpdateInputInfoMapper.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/policy/mappers/PolicyUpdateInputInfoMapper.java index cb323b60dd465..69c3913bc9da6 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/policy/mappers/PolicyUpdateInputInfoMapper.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/policy/mappers/PolicyUpdateInputInfoMapper.java @@ -51,8 +51,16 @@ private DataHubActorFilter mapActors(final ActorFilterInput actorInput) { result.setAllGroups(actorInput.getAllGroups()); result.setAllUsers(actorInput.getAllUsers()); result.setResourceOwners(actorInput.getResourceOwners()); + result.setPlatformInstanceOwners(actorInput.getPlatformInstanceOwners()); if (actorInput.getResourceOwnersTypes() != null) { - result.setResourceOwnersTypes(new UrnArray(actorInput.getResourceOwnersTypes().stream().map(this::createUrn).collect(Collectors.toList()))); + result.setResourceOwnersTypes( + new UrnArray(actorInput.getResourceOwnersTypes().stream().map(this::createUrn).collect(Collectors.toList())) + ); + } + if (actorInput.getPlatformInstanceOwnersTypes() != null) { + result.setPlatformInstanceOwnersTypes( + new UrnArray(actorInput.getPlatformInstanceOwnersTypes().stream().map(this::createUrn).collect(Collectors.toList())) + ); } if (actorInput.getGroups() != null) { result.setGroups(new UrnArray(actorInput.getGroups().stream().map(this::createUrn).collect(Collectors.toList()))); diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/policy/DataHubPolicyMapper.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/policy/DataHubPolicyMapper.java index 167e1615fc4cc..862d1321b20a5 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/policy/DataHubPolicyMapper.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/policy/DataHubPolicyMapper.java @@ -68,11 +68,16 @@ private ActorFilter mapActors(final DataHubActorFilter actorFilter) { result.setAllGroups(actorFilter.isAllGroups()); result.setAllUsers(actorFilter.isAllUsers()); result.setResourceOwners(actorFilter.isResourceOwners()); + result.setPlatformInstanceOwners(actorFilter.isPlatformInstanceOwners()); // Change here is not executed at the moment - leaving it for the future UrnArray resourceOwnersTypes = actorFilter.getResourceOwnersTypes(); if (resourceOwnersTypes != null) { result.setResourceOwnersTypes(resourceOwnersTypes.stream().map(Urn::toString).collect(Collectors.toList())); } + UrnArray platformInstanceOwnersTypes = actorFilter.getPlatformInstanceOwnersTypes(); + if (platformInstanceOwnersTypes != null) { + result.setPlatformInstanceOwnersTypes(platformInstanceOwnersTypes.stream().map(Urn::toString).collect(Collectors.toList())); + } if (actorFilter.hasGroups()) { result.setGroups(actorFilter.getGroups().stream().map(Urn::toString).collect(Collectors.toList())); } diff --git a/datahub-graphql-core/src/main/resources/entity.graphql b/datahub-graphql-core/src/main/resources/entity.graphql index 044c405942a3c..56b14c14c28e4 100644 --- a/datahub-graphql-core/src/main/resources/entity.graphql +++ b/datahub-graphql-core/src/main/resources/entity.graphql @@ -8122,7 +8122,23 @@ type ActorFilter { """ Set of OwnershipTypes to apply the policy to (if resourceOwners field is set to True), resolved. """ - resolvedOwnershipTypes: [OwnershipTypeEntity!] + resolvedResourceOwnershipTypes: [OwnershipTypeEntity!] + + """ + Whether the filter should return TRUE for platform instance owners of a particular resource + Only applies to policies of type METADATA, which have a resource associated with them + """ + platformInstanceOwners: Boolean! + + """ + Set of OwnershipTypes to apply the policy to (if platformInstanceOwners field is set to True) + """ + platformInstanceOwnersTypes: [String!] + + """ + Set of OwnershipTypes to apply the policy to (if platformInstanceOwners field is set to True), resolved. + """ + resolvedPlatformInstanceOwnershipTypes: [OwnershipTypeEntity!] """ Whether the filter should apply to all users @@ -8257,6 +8273,17 @@ input ActorFilterInput { """ resourceOwnersTypes: [String!] + """ + Whether the filter should return TRUE for platform instance owners of a particular resource + Only applies to policies of type METADATA, which have a resource associated with them + """ + platformInstanceOwners: Boolean! + + """ + Set of OwnershipTypes to apply the policy to (if platformInstanceOwners field is set to True) + """ + platformInstanceOwnersTypes: [String!] + """ Whether the filter should apply to all users """ diff --git a/datahub-web-react/src/app/permissions/policy/ManagePolicies.tsx b/datahub-web-react/src/app/permissions/policy/ManagePolicies.tsx index 08327d40a7165..d877fee86071b 100644 --- a/datahub-web-react/src/app/permissions/policy/ManagePolicies.tsx +++ b/datahub-web-react/src/app/permissions/policy/ManagePolicies.tsx @@ -110,6 +110,8 @@ const toPolicyInput = (policy: Omit): PolicyUpdateInput => { allGroups: policy.actors.allGroups, resourceOwners: policy.actors.resourceOwners, resourceOwnersTypes: policy.actors.resourceOwnersTypes, + platformInstanceOwners: policy.actors.platformInstanceOwners, + platformInstanceOwnersTypes: policy.actors.platformInstanceOwnersTypes, }, }; if (policy.resources !== null && policy.resources !== undefined) { @@ -360,7 +362,8 @@ export const ManagePolicies = () => { /> {record?.allUsers ? All Users : null} {record?.allGroups ? All Groups : null} - {record?.resourceOwners ? All Owners : null} + {record?.resourceOwners ? All Resource Owners : null} + {record?.platformInstanceOwners ? All Platform Instance Owners : null} ); }, @@ -430,6 +433,7 @@ export const ManagePolicies = () => { allGroups: policy?.actors?.allGroups, allUsers: policy?.actors?.allUsers, resourceOwners: policy?.actors?.resourceOwners, + platformInstanceOwners: policy?.actors?.platformInstanceOwners, description: policy?.description, editable: policy?.editable, name: policy?.name, diff --git a/datahub-web-react/src/app/permissions/policy/PolicyActorForm.tsx b/datahub-web-react/src/app/permissions/policy/PolicyActorForm.tsx index adb660d43f471..48c4dc4fece53 100644 --- a/datahub-web-react/src/app/permissions/policy/PolicyActorForm.tsx +++ b/datahub-web-react/src/app/permissions/policy/PolicyActorForm.tsx @@ -61,8 +61,8 @@ export default function PolicyActorForm({ policyType, actors, setActors }: Props ownershipData?.listOwnershipTypes?.ownershipTypes.filter((type) => type.urn !== 'urn:li:ownershipType:none') || []; const ownershipTypesMap = Object.fromEntries(ownershipTypes.map((type) => [type.urn, type.info?.name])); - // Toggle the "Owners" switch - const onToggleAppliesToOwners = (value: boolean) => { + // Toggle the "Resource Owners" switch + const onToggleAppliesToResourceOwners = (value: boolean) => { setActors({ ...actors, resourceOwners: value, @@ -70,7 +70,7 @@ export default function PolicyActorForm({ policyType, actors, setActors }: Props }); }; - const onSelectOwnershipTypeActor = (newType: string) => { + const onSelectResourceOwnershipTypeActor = (newType: string) => { const newResourceOwnersTypes: Maybe = [...(actors.resourceOwnersTypes || []), newType]; setActors({ ...actors, @@ -78,13 +78,42 @@ export default function PolicyActorForm({ policyType, actors, setActors }: Props }); }; - const onDeselectOwnershipTypeActor = (type: string) => { + const onDeselectResourceOwnershipTypeActor = (type: string) => { const newResourceOwnersTypes: Maybe = actors.resourceOwnersTypes?.filter((u: string) => u !== type); setActors({ ...actors, resourceOwnersTypes: newResourceOwnersTypes?.length ? newResourceOwnersTypes : null, }); }; + // Toggle the "Platform Instance Owners" switch + const onToggleAppliesToPlatformInstanceOwners = (value: boolean) => { + setActors({ + ...actors, + platformInstanceOwners: value, + platformInstanceOwnersTypes: value ? actors.platformInstanceOwnersTypes : null, + }); + }; + + const onSelectPlatformInstanceOwnershipTypeActor = (newType: string) => { + const newPlatformInstanceOwnersTypes: Maybe = [ + ...(actors.platformInstanceOwnersTypes || []), + newType, + ]; + setActors({ + ...actors, + platformInstanceOwnersTypes: newPlatformInstanceOwnersTypes, + }); + }; + + const onDeselectPlatformInstanceOwnershipTypeActor = (type: string) => { + const newPlatformInstanceOwnersTypes: Maybe = actors.platformInstanceOwnersTypes?.filter( + (u: string) => u !== type, + ); + setActors({ + ...actors, + platformInstanceOwnersTypes: newPlatformInstanceOwnersTypes?.length ? newPlatformInstanceOwnersTypes : null, + }); + }; // When a user search result is selected, add the urn to the ActorFilter const onSelectUserActor = (newUser: string) => { @@ -206,7 +235,8 @@ export default function PolicyActorForm({ policyType, actors, setActors }: Props // Select dropdown values. const usersSelectValue = actors.allUsers ? ['All'] : actors.users || []; const groupsSelectValue = actors.allGroups ? ['All'] : actors.groups || []; - const ownershipTypesSelectValue = actors.resourceOwnersTypes || []; + const resourceOwnershipTypesSelectValue = actors.resourceOwnersTypes || []; + const platformInstanceOwnershipTypesSelectValue = actors.platformInstanceOwnersTypes || []; const tagRender = (props) => { // eslint-disable-next-line react/prop-types @@ -240,13 +270,13 @@ export default function PolicyActorForm({ policyType, actors, setActors }: Props Select the users & groups that this policy should apply to. {showAppliesToOwners && ( - Owners} labelAlign="right"> + Resource Owners} labelAlign="right"> - Whether this policy should be apply to owners of the Metadata asset. If true, those who are - marked as owners of a Metadata Asset, either directly or indirectly via a Group, will have the - selected privileges. + Whether this policy should apply to owners of the Metadata asset. If true, those who are marked + as owners of a Metadata Asset, either directly or indirectly via a Group, will have the selected + privileges. - + {actors.resourceOwners && ( @@ -254,11 +284,58 @@ export default function PolicyActorForm({ policyType, actors, setActors }: Props will applied to any type of ownership. + + )} + + )} + {showAppliesToOwners && ( + Platform Instance Owners} + labelAlign="right" + > + + Whether this policy should apply to platform instance owners of the Metadata asset. If true, + those who are marked as owners of the platform instance to which a Metadata Asset belongs to, + either directly or indirectly via a Group, will have the selected privileges. + + + {actors.platformInstanceOwners && ( + + + List of types of ownership which will be used to match plafrom instance owners. If + empty, the policies will applied to any type of ownership. + +