From cbcc00bc78c796c55a2b1422e0d391a4afda46d4 Mon Sep 17 00:00:00 2001 From: Suresh Srinivas Date: Tue, 9 Aug 2022 14:25:27 -0700 Subject: [PATCH] Fixes #6659 Backend : Add support for roles and teams in policy (#6676) --- .../catalog/jdbi3/PolicyRepository.java | 17 ++++++++ .../catalog/jdbi3/UserRepository.java | 6 +-- .../resources/policies/PolicyResource.java | 4 +- .../openmetadata/catalog/util/EntityUtil.java | 12 ++++++ .../json/schema/entity/policies/policy.json | 8 ++++ .../policies/PolicyResourceTest.java | 39 ++++++++++++++++++- ingestion-core/src/metadata/_version.py | 2 +- 7 files changed, 82 insertions(+), 6 deletions(-) diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/PolicyRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/PolicyRepository.java index 14ab162e9d6..f63aa8c5067 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/PolicyRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/PolicyRepository.java @@ -28,6 +28,7 @@ import org.openmetadata.catalog.Entity; import org.openmetadata.catalog.entity.data.Location; import org.openmetadata.catalog.entity.policies.Policy; import org.openmetadata.catalog.exception.CatalogExceptionMessage; +import org.openmetadata.catalog.jdbi3.CollectionDAO.EntityRelationshipRecord; import org.openmetadata.catalog.resources.policies.PolicyResource; import org.openmetadata.catalog.type.EntityReference; import org.openmetadata.catalog.type.PolicyType; @@ -63,9 +64,25 @@ public class PolicyRepository extends EntityRepository { public Policy setFields(Policy policy, Fields fields) throws IOException { policy.setOwner(fields.contains(FIELD_OWNER) ? getOwner(policy) : null); policy.setLocation(fields.contains("location") ? getLocationForPolicy(policy) : null); + policy.setTeams(fields.contains("teams") ? getTeams(policy) : null); + policy.setRoles(fields.contains("roles") ? getRoles(policy) : null); return policy; } + /* Get all the teams that use this policy */ + private List getTeams(Policy policy) throws IOException { + List records = findFrom(policy.getId(), POLICY, Relationship.HAS, Entity.TEAM); + List teams = EntityUtil.populateEntityReferences(records, Entity.TEAM); + return teams; + } + + /* Get all the roles that use this policy */ + private List getRoles(Policy policy) throws IOException { + List records = findFrom(policy.getId(), POLICY, Relationship.HAS, Entity.ROLE); + List roles = EntityUtil.populateEntityReferences(records, Entity.ROLE); + return roles; + } + /** Generate EntityReference for a given Policy's Location. * */ @Transaction private EntityReference getLocationReference(Policy policy) throws IOException { diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/UserRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/UserRepository.java index a93475d1242..f5f7e343982 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/UserRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/UserRepository.java @@ -204,20 +204,20 @@ public class UserRepository extends EntityRepository { return EntityUtil.populateEntityReferences(refs); } - /* Add all the roles that user has been assigned and inherited from the team to User entity */ + /* Get all the roles that user has been assigned and inherited from the team to User entity */ private List getRoles(User user) throws IOException { List roleIds = findTo(user.getId(), Entity.USER, Relationship.HAS, Entity.ROLE); return EntityUtil.populateEntityReferences(roleIds, Entity.ROLE); } - /* Add all the roles that user has been assigned and inherited from the team to User entity */ + /* Get all the roles that user has been assigned and inherited from the team to User entity */ private List getInheritedRoles(User user) throws IOException { List roles = getDefaultRole(); roles.addAll(getTeamDefaultRoles(user)); return roles.stream().distinct().collect(Collectors.toList()); // Remove duplicates } - /* Add all the teams that user belongs to User entity */ + /* Get all the teams that user belongs to User entity */ private List getTeams(User user) throws IOException { List records = findFrom(user.getId(), Entity.USER, Relationship.HAS, Entity.TEAM); List teams = EntityUtil.populateEntityReferences(records, Entity.TEAM); diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/policies/PolicyResource.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/policies/PolicyResource.java index 95933547bb0..33ce2bf6fe9 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/policies/PolicyResource.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/policies/PolicyResource.java @@ -81,6 +81,8 @@ public class PolicyResource extends EntityResource { @Override public Policy addHref(UriInfo uriInfo, Policy policy) { Entity.withHref(uriInfo, policy.getOwner()); + Entity.withHref(uriInfo, policy.getTeams()); + Entity.withHref(uriInfo, policy.getRoles()); return policy; } @@ -117,7 +119,7 @@ public class PolicyResource extends EntityResource { } } - public static final String FIELDS = "owner,location"; + public static final String FIELDS = "owner,location,teams,roles"; @GET @Valid diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/util/EntityUtil.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/util/EntityUtil.java index 914b286e4dd..c874f48d26d 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/util/EntityUtil.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/util/EntityUtil.java @@ -38,6 +38,7 @@ import org.apache.http.client.HttpResponseException; import org.joda.time.Period; import org.joda.time.format.ISOPeriodFormat; import org.openmetadata.catalog.Entity; +import org.openmetadata.catalog.EntityInterface; import org.openmetadata.catalog.api.data.TermReference; import org.openmetadata.catalog.entity.data.GlossaryTerm; import org.openmetadata.catalog.entity.data.Table; @@ -263,6 +264,17 @@ public final class EntityUtil { return CommonUtil.getResources(Pattern.compile(path)); } + public static List toEntityReferences(List entities) { + if (entities == null) { + return null; + } + List entityReferences = new ArrayList<>(); + for (T entity : entities) { + entityReferences.add(entity.getEntityReference()); + } + return entityReferences; + } + public static List toEntityReferences(List ids, String entityType) { if (ids == null) { return null; diff --git a/catalog-rest-service/src/main/resources/json/schema/entity/policies/policy.json b/catalog-rest-service/src/main/resources/json/schema/entity/policies/policy.json index d837994eebb..cd088d1803b 100644 --- a/catalog-rest-service/src/main/resources/json/schema/entity/policies/policy.json +++ b/catalog-rest-service/src/main/resources/json/schema/entity/policies/policy.json @@ -94,6 +94,14 @@ "description": "Set of rules that the policy contains.", "$ref": "#/definitions/rules" }, + "teams" : { + "description": "Teams that use this policy directly and not through roles.", + "$ref": "../../type/entityReference.json#/definitions/entityReferenceList" + }, + "roles" : { + "description": "Roles that use this policy.", + "$ref": "../../type/entityReference.json#/definitions/entityReferenceList" + }, "location": { "description": "Location to which a policy is applied. This field is relevant only for `lifeCycle` policies.", "$ref": "../../type/entityReference.json", diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/policies/PolicyResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/policies/PolicyResourceTest.java index b9c0d5b559f..906af70ad6c 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/policies/PolicyResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/policies/PolicyResourceTest.java @@ -41,14 +41,20 @@ import org.junit.jupiter.api.TestInfo; import org.openmetadata.catalog.Entity; import org.openmetadata.catalog.api.data.CreateLocation; import org.openmetadata.catalog.api.policies.CreatePolicy; +import org.openmetadata.catalog.api.teams.CreateRole; +import org.openmetadata.catalog.api.teams.CreateTeam; import org.openmetadata.catalog.entity.data.Location; import org.openmetadata.catalog.entity.policies.Policy; import org.openmetadata.catalog.entity.policies.accessControl.Rule; import org.openmetadata.catalog.entity.policies.accessControl.Rule.Effect; +import org.openmetadata.catalog.entity.teams.Role; +import org.openmetadata.catalog.entity.teams.Team; import org.openmetadata.catalog.resources.EntityResourceTest; import org.openmetadata.catalog.resources.locations.LocationResourceTest; import org.openmetadata.catalog.resources.policies.PolicyResource.PolicyList; import org.openmetadata.catalog.resources.policies.PolicyResource.ResourceDescriptorList; +import org.openmetadata.catalog.resources.teams.RoleResourceTest; +import org.openmetadata.catalog.resources.teams.TeamResourceTest; import org.openmetadata.catalog.type.ChangeDescription; import org.openmetadata.catalog.type.EntityReference; import org.openmetadata.catalog.type.FieldChange; @@ -183,7 +189,6 @@ public class PolicyResourceTest extends EntityResourceTest // Get list of policy resources and make sure it has all the entities and other resources ResourceDescriptorList actualResourceDescriptors = getPolicyResources(ADMIN_AUTH_HEADERS); assertNotNull(actualResourceDescriptors.getData()); - System.out.println(actualResourceDescriptors.getData()); // Ensure all entities are captured in resource descriptor list List entities = Entity.getEntityList(); @@ -194,6 +199,38 @@ public class PolicyResourceTest extends EntityResourceTest } } + @Test + void get_policyTeamsAndRoles(TestInfo test) throws IOException { + // Ensure policy returns teams and roles that are part of + + // Create 5 policies + List policies = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + CreatePolicy create = createRequest(test, i); + policies.add(createEntity(create, ADMIN_AUTH_HEADERS)); + } + + TeamResourceTest teamResourceTest = new TeamResourceTest(); + List teams = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + // Team X has Policy X + CreateTeam createTeam = teamResourceTest.createRequest(test, i).withPolicies(List.of(policies.get(i).getId())); + teams.add(teamResourceTest.createEntity(createTeam, ADMIN_AUTH_HEADERS)); + } + + // Create a role with all the policies + RoleResourceTest roleResourceTest = new RoleResourceTest(); + CreateRole createRole = roleResourceTest.createRequest(test).withPolicies(EntityUtil.toEntityReferences(policies)); + Role role = roleResourceTest.createEntity(createRole, ADMIN_AUTH_HEADERS); + + // Get each policy and ensure the teams and roles are listed correctly + for (int i = 0; i < 3; i++) { + Policy getPolicy = getEntity(policies.get(i).getId(), "teams,roles", ADMIN_AUTH_HEADERS); + assertReference(teams.get(i).getEntityReference(), getPolicy.getTeams().get(0)); + assertReference(role.getEntityReference(), getPolicy.getRoles().get(0)); + } + } + @Override public Policy validateGetWithDifferentFields(Policy policy, boolean byName) throws HttpResponseException { String fields = ""; diff --git a/ingestion-core/src/metadata/_version.py b/ingestion-core/src/metadata/_version.py index 53ed605c872..99e8a03ec79 100644 --- a/ingestion-core/src/metadata/_version.py +++ b/ingestion-core/src/metadata/_version.py @@ -7,5 +7,5 @@ Provides metadata version information. from incremental import Version -__version__ = Version("metadata", 0, 12, 0, dev=9) +__version__ = Version("metadata", 0, 12, 0, dev=10) __all__ = ["__version__"]