diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/EntityRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/EntityRepository.java index 7ed91098e02..07ca70452f6 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/EntityRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/EntityRepository.java @@ -972,13 +972,23 @@ public abstract class EntityRepository { } } - public void validateRoles(List entityReferences) throws IOException { - if (entityReferences != null) { - for (EntityReference entityReference : entityReferences) { + public void validateRoles(List roles) throws IOException { + if (roles != null) { + for (EntityReference entityReference : roles) { EntityReference ref = daoCollection.roleDAO().findEntityReferenceById(entityReference.getId()); EntityUtil.copy(ref, entityReference); } - entityReferences.sort(EntityUtil.compareEntityReference); + roles.sort(EntityUtil.compareEntityReference); + } + } + + void validatePolicies(List policies) throws IOException { + if (policies != null) { + for (EntityReference entityReference : policies) { + EntityReference ref = daoCollection.policyDAO().findEntityReferenceById(entityReference.getId()); + EntityUtil.copy(ref, entityReference); + } + policies.sort(EntityUtil.compareEntityReference); } } diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/TeamRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/TeamRepository.java index 49b2d20e109..1660a82100b 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/TeamRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/TeamRepository.java @@ -14,6 +14,7 @@ package org.openmetadata.catalog.jdbi3; import static org.openmetadata.catalog.Entity.FIELD_OWNER; +import static org.openmetadata.catalog.Entity.POLICY; import static org.openmetadata.catalog.Entity.TEAM; import static org.openmetadata.catalog.api.teams.CreateTeam.TeamType.BUSINESS_UNIT; import static org.openmetadata.catalog.api.teams.CreateTeam.TeamType.DEPARTMENT; @@ -46,8 +47,8 @@ import org.openmetadata.catalog.util.JsonUtils; @Slf4j public class TeamRepository extends EntityRepository { - static final String TEAM_UPDATE_FIELDS = "owner,profile,users,defaultRoles,parents,children"; - static final String TEAM_PATCH_FIELDS = "owner,profile,users,defaultRoles,parents,children"; + static final String TEAM_UPDATE_FIELDS = "owner,profile,users,defaultRoles,parents,children,policies"; + static final String TEAM_PATCH_FIELDS = "owner,profile,users,defaultRoles,parents,children,policies"; Team organization = null; public TeamRepository(CollectionDAO dao) { @@ -65,6 +66,7 @@ public class TeamRepository extends EntityRepository { team.setOwner(fields.contains(FIELD_OWNER) ? getOwner(team) : null); team.setParents(fields.contains("parents") ? getParents(team) : null); team.setChildren(fields.contains("children") ? getChildren(team) : null); + team.setPolicies(fields.contains("policies") ? getPolicies(team) : null); return team; } @@ -82,6 +84,7 @@ public class TeamRepository extends EntityRepository { populateChildren(team); // Validate children validateUsers(team.getUsers()); validateRoles(team.getDefaultRoles()); + validatePolicies(team.getPolicies()); } @Override @@ -92,6 +95,7 @@ public class TeamRepository extends EntityRepository { List defaultRoles = team.getDefaultRoles(); List parents = team.getParents(); List children = team.getChildren(); + List policies = team.getPolicies(); // Don't store users, defaultRoles, href as JSON. Build it on the fly based on relationships team.withUsers(null).withDefaultRoles(null).withHref(null).withOwner(null); @@ -99,7 +103,12 @@ public class TeamRepository extends EntityRepository { store(team.getId(), team, update); // Restore the relationships - team.withUsers(users).withDefaultRoles(defaultRoles).withOwner(owner).withParents(parents).withChildren(children); + team.withUsers(users) + .withDefaultRoles(defaultRoles) + .withOwner(owner) + .withParents(parents) + .withChildren(children) + .withPolicies(policies); } @Override @@ -118,6 +127,9 @@ public class TeamRepository extends EntityRepository { for (EntityReference child : listOrEmpty(team.getChildren())) { addRelationship(team.getId(), child.getId(), TEAM, TEAM, Relationship.PARENT_OF); } + for (EntityReference policy : listOrEmpty(team.getPolicies())) { + addRelationship(team.getId(), policy.getId(), TEAM, POLICY, Relationship.HAS); + } } @Override @@ -166,6 +178,11 @@ public class TeamRepository extends EntityRepository { return EntityUtil.populateEntityReferences(children, TEAM); } + private List getPolicies(Team team) throws IOException { + List policies = findTo(team.getId(), TEAM, Relationship.HAS, POLICY); + return EntityUtil.populateEntityReferences(policies, POLICY); + } + private void populateChildren(Team team) throws IOException { List childrenRefs = team.getChildren(); if (childrenRefs == null) { @@ -188,7 +205,7 @@ public class TeamRepository extends EntityRepository { } private void populateParents(Team team) throws IOException { - // All the teams created without parents has the top Organization as the default parent + // Teams created without parents has the top Organization as the default parent List parentRefs = team.getParents(); if (parentRefs == null) { team.setParents(new ArrayList<>()); @@ -217,7 +234,8 @@ public class TeamRepository extends EntityRepository { // Populate team refs from team entity list private void populateTeamRefs(List teamRefs, List teams) { for (int i = 0; i < teams.size(); i++) { - EntityUtil.copy(teamRefs.get(i), teams.get(i).getEntityReference()); + System.out.print("XXX copying " + teams.get(i).getEntityReference()); + EntityUtil.copy(teams.get(i).getEntityReference(), teamRefs.get(i)); } } @@ -295,6 +313,7 @@ public class TeamRepository extends EntityRepository { updateDefaultRoles(original, updated); updateParents(original, updated); updateChildren(original, updated); + updatePolicies(original, updated); } private void updateUsers(Team origTeam, Team updatedTeam) throws JsonProcessingException { @@ -329,7 +348,14 @@ public class TeamRepository extends EntityRepository { List origParents = listOrEmpty(original.getChildren()); List updatedParents = listOrEmpty(updated.getChildren()); updateToRelationships( - "parents", TEAM, original.getId(), Relationship.PARENT_OF, TEAM, origParents, updatedParents, false); + "children", TEAM, original.getId(), Relationship.PARENT_OF, TEAM, origParents, updatedParents, false); + } + + private void updatePolicies(Team original, Team updated) throws JsonProcessingException { + List origPolicies = listOrEmpty(original.getPolicies()); + List updatedPolicies = listOrEmpty(updated.getPolicies()); + updateToRelationships( + "policies", TEAM, original.getId(), Relationship.HAS, POLICY, origPolicies, updatedPolicies, false); } } } diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/teams/TeamResource.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/teams/TeamResource.java index 834c37e8b1a..5c555a2bd3d 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/teams/TeamResource.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/teams/TeamResource.java @@ -75,6 +75,9 @@ public class TeamResource extends EntityResource { Entity.withHref(uriInfo, team.getUsers()); Entity.withHref(uriInfo, team.getDefaultRoles()); Entity.withHref(uriInfo, team.getOwns()); + Entity.withHref(uriInfo, team.getParents()); + Entity.withHref(uriInfo, team.getChildren()); + Entity.withHref(uriInfo, team.getPolicies()); return team; } @@ -96,7 +99,7 @@ public class TeamResource extends EntityResource { } } - static final String FIELDS = "owner,profile,users,owns,defaultRoles,parents,children"; + static final String FIELDS = "owner,profile,users,owns,defaultRoles,parents,children,policies"; @GET @Valid @@ -358,6 +361,7 @@ public class TeamResource extends EntityResource { .withDefaultRoles(EntityUtil.toEntityReferences(ct.getDefaultRoles(), Entity.ROLE)) .withTeamType(ct.getTeamType()) .withParents(EntityUtil.toEntityReferences(ct.getParents(), Entity.TEAM)) - .withChildren(EntityUtil.toEntityReferences(ct.getChildren(), Entity.TEAM)); + .withChildren(EntityUtil.toEntityReferences(ct.getChildren(), Entity.TEAM)) + .withPolicies(EntityUtil.toEntityReferences(ct.getPolicies(), Entity.POLICY)); } } diff --git a/catalog-rest-service/src/main/resources/json/schema/api/teams/createTeam.json b/catalog-rest-service/src/main/resources/json/schema/api/teams/createTeam.json index db38b12fea7..8b28721c554 100644 --- a/catalog-rest-service/src/main/resources/json/schema/api/teams/createTeam.json +++ b/catalog-rest-service/src/main/resources/json/schema/api/teams/createTeam.json @@ -68,6 +68,14 @@ "description": "Can any user join this team during sign up? Value of true indicates yes, and false no.", "type": "boolean", "default": true + }, + "policies": { + "description": "Policies that is attached to this team.", + "type": "array", + "items": { + "$ref": "../../type/basic.json#/definitions/uuid" + }, + "default": null } }, "required": ["name", "teamType"], diff --git a/catalog-rest-service/src/main/resources/json/schema/entity/teams/team.json b/catalog-rest-service/src/main/resources/json/schema/entity/teams/team.json index 59087e325af..1c0456f522b 100644 --- a/catalog-rest-service/src/main/resources/json/schema/entity/teams/team.json +++ b/catalog-rest-service/src/main/resources/json/schema/entity/teams/team.json @@ -102,6 +102,10 @@ "defaultRoles": { "description": "Default roles of a team. These roles will be inherited by all the users that are part of this team.", "$ref": "../../type/entityReference.json#/definitions/entityReferenceList" + }, + "policies": { + "description": "Policies that is attached to this team.", + "$ref": "../../type/entityReference.json#/definitions/entityReferenceList" } }, "required": ["id", "name", "href"], diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/EntityResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/EntityResourceTest.java index 6d5f9aa5e33..1f916d9453b 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/EntityResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/EntityResourceTest.java @@ -99,6 +99,7 @@ import org.openmetadata.catalog.entity.data.Database; import org.openmetadata.catalog.entity.data.DatabaseSchema; import org.openmetadata.catalog.entity.data.Glossary; import org.openmetadata.catalog.entity.data.GlossaryTerm; +import org.openmetadata.catalog.entity.policies.Policy; import org.openmetadata.catalog.entity.services.DashboardService; import org.openmetadata.catalog.entity.services.DatabaseService; import org.openmetadata.catalog.entity.services.MessagingService; @@ -117,6 +118,7 @@ import org.openmetadata.catalog.resources.events.EventResource.ChangeEventList; import org.openmetadata.catalog.resources.events.WebhookResourceTest; import org.openmetadata.catalog.resources.glossary.GlossaryResourceTest; import org.openmetadata.catalog.resources.metadata.TypeResourceTest; +import org.openmetadata.catalog.resources.policies.PolicyResourceTest; import org.openmetadata.catalog.resources.services.DashboardServiceResourceTest; import org.openmetadata.catalog.resources.services.DatabaseServiceResourceTest; import org.openmetadata.catalog.resources.services.MessagingServiceResourceTest; @@ -187,6 +189,9 @@ public abstract class EntityResourceTest location = createLocation(); } + public void setupPolicies() throws HttpResponseException { + POLICY1 = createEntity(createRequest("policy1"), ADMIN_AUTH_HEADERS); + POLICY2 = createEntity(createRequest("policy2"), ADMIN_AUTH_HEADERS); + } + @Override public CreatePolicy createRequest(String name) { return new CreatePolicy().withName(name).withPolicyType(PolicyType.Lifecycle); diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/teams/RoleResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/teams/RoleResourceTest.java index 1232ade161a..563916677f2 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/teams/RoleResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/teams/RoleResourceTest.java @@ -23,7 +23,6 @@ import static org.openmetadata.catalog.util.TestUtils.ADMIN_AUTH_HEADERS; import static org.openmetadata.catalog.util.TestUtils.TEST_AUTH_HEADERS; import static org.openmetadata.catalog.util.TestUtils.TEST_USER_NAME; import static org.openmetadata.catalog.util.TestUtils.UpdateType.MINOR_UPDATE; -import static org.openmetadata.catalog.util.TestUtils.assertEntityReferenceList; import static org.openmetadata.catalog.util.TestUtils.assertListNotNull; import static org.openmetadata.catalog.util.TestUtils.assertListNull; import static org.openmetadata.catalog.util.TestUtils.assertResponse; @@ -230,7 +229,7 @@ public class RoleResourceTest extends EntityResourceTest { @Override public void validateCreatedEntity(Role role, CreateRole createRequest, Map authHeaders) { - assertEntityReferenceList(role.getPolicies(), createRequest.getPolicies()); + TestUtils.assertEntityReferences(role.getPolicies(), createRequest.getPolicies()); } @Override diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/teams/TeamResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/teams/TeamResourceTest.java index c19a96756ad..a2ef4787d77 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/teams/TeamResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/teams/TeamResourceTest.java @@ -416,6 +416,258 @@ public class TeamResourceTest extends EntityResourceTest { patchEntityAndCheck(bu2, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change2); } + @Test + void patch_isJoinable_200(TestInfo test) throws IOException { + CreateTeam create = + createRequest(getEntityName(test), "description", "displayName", null) + .withProfile(PROFILE) + .withIsJoinable(false); + Team team = createAndCheckEntity(create, ADMIN_AUTH_HEADERS); + + // patch the team with isJoinable set to true + String json = JsonUtils.pojoToJson(team); + team.setIsJoinable(true); + ChangeDescription change = getChangeDescription(team.getVersion()); + change.getFieldsUpdated().add(new FieldChange().withName("isJoinable").withOldValue(false).withNewValue(true)); + team = patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, UpdateType.MINOR_UPDATE, change); + + // set isJoinable to false and check + json = JsonUtils.pojoToJson(team); + team.setIsJoinable(false); + change = getChangeDescription(team.getVersion()); + change.getFieldsUpdated().add(new FieldChange().withName("isJoinable").withOldValue(true).withNewValue(false)); + patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, UpdateType.MINOR_UPDATE, change); + } + + @Test + void patch_deleteUserAndDefaultRoleFromTeam_200(TestInfo test) throws IOException { + UserResourceTest userResourceTest = new UserResourceTest(); + final int totalUsers = 20; + ArrayList users = new ArrayList<>(); + for (int i = 0; i < totalUsers; i++) { + User user = userResourceTest.createEntity(userResourceTest.createRequest(test, i), ADMIN_AUTH_HEADERS); + users.add(user.getId()); + } + + RoleResourceTest roleResourceTest = new RoleResourceTest(); + roleResourceTest.createRolesAndSetDefault(test, 5, 0); + List roles = roleResourceTest.listEntities(Map.of(), ADMIN_AUTH_HEADERS).getData(); + List rolesIds = roles.stream().map(Role::getId).collect(Collectors.toList()); + + CreateTeam create = + createRequest(getEntityName(test), "description", "displayName", null) + .withProfile(PROFILE) + .withUsers(users) + .withDefaultRoles(rolesIds); + Team team = createAndCheckEntity(create, ADMIN_AUTH_HEADERS); + + // Remove a user from the team using patch request + String json = JsonUtils.pojoToJson(team); + int removeUserIndex = new Random().nextInt(totalUsers); + EntityReference deletedUser = team.getUsers().get(removeUserIndex); + team.getUsers().remove(removeUserIndex); + ChangeDescription change = getChangeDescription(team.getVersion()); + change.getFieldsDeleted().add(new FieldChange().withName("users").withOldValue(Arrays.asList(deletedUser))); + team = patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, UpdateType.MINOR_UPDATE, change); + + // Remove a default role from the team using patch request + json = JsonUtils.pojoToJson(team); + int removeDefaultRoleIndex = new Random().nextInt(roles.size()); + EntityReference deletedRole = team.getDefaultRoles().get(removeDefaultRoleIndex); + team.getDefaultRoles().remove(removeDefaultRoleIndex); + change = getChangeDescription(team.getVersion()); + change.getFieldsDeleted().add(new FieldChange().withName("defaultRoles").withOldValue(Arrays.asList(deletedRole))); + patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, UpdateType.MINOR_UPDATE, change); + } + + @Test + void post_teamWithPolicies(TestInfo test) throws IOException { + System.out.println("XXX " + POLICY1); + System.out.println("XXX " + POLICY2); + CreateTeam create = createRequest(getEntityName(test)).withPolicies(List.of(POLICY1.getId(), POLICY2.getId())); + createAndCheckEntity(create, ADMIN_AUTH_HEADERS); + } + + @Test + void put_teamWithPolicies(TestInfo test) throws IOException { + CreateTeam create = createRequest(getEntityName(test)); + Team team = createAndCheckEntity(create, ADMIN_AUTH_HEADERS); + + // Add policies to the team + create = createRequest(getEntityName(test)).withPolicies(List.of(POLICY1.getId(), POLICY2.getId())); + ChangeDescription change = getChangeDescription(team.getVersion()); + change + .getFieldsAdded() + .add( + new FieldChange() + .withName("policies") + .withNewValue(List.of(POLICY1.getEntityReference(), POLICY2.getEntityReference()))); + team = updateAndCheckEntity(create, OK, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); + + // Remove policies from the team + create = createRequest(getEntityName(test)); + change = getChangeDescription(team.getVersion()); + change + .getFieldsDeleted() + .add( + new FieldChange() + .withName("policies") + .withOldValue(List.of(POLICY1.getEntityReference(), POLICY2.getEntityReference()))); + updateAndCheckEntity(create, OK, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); + } + + @Test + void patch_teamWithPolicies(TestInfo test) throws IOException { + CreateTeam create = createRequest(getEntityName(test)); + Team team = createAndCheckEntity(create, ADMIN_AUTH_HEADERS); + + // Add policies to the team + String json = JsonUtils.pojoToJson(team); + team.withPolicies(List.of(POLICY1.getEntityReference(), POLICY2.getEntityReference())); + ChangeDescription change = getChangeDescription(team.getVersion()); + change + .getFieldsAdded() + .add( + new FieldChange() + .withName("policies") + .withNewValue(List.of(POLICY1.getEntityReference(), POLICY2.getEntityReference()))); + team = patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); + + // Remove policies from the team + json = JsonUtils.pojoToJson(team); + team.withPolicies(null); + change = getChangeDescription(team.getVersion()); + change + .getFieldsDeleted() + .add( + new FieldChange() + .withName("policies") + .withOldValue(List.of(POLICY1.getEntityReference(), POLICY2.getEntityReference()))); + patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); + } + + private static void validateTeam( + Team team, + String expectedDescription, + String expectedDisplayName, + Profile expectedProfile, + List expectedUsers, + List expectedDefaultRoles, + String expectedUpdatedBy) { + assertListNotNull(team.getId(), team.getHref()); + assertEquals(expectedDescription, team.getDescription()); + assertEquals(expectedUpdatedBy, team.getUpdatedBy()); + assertEquals(expectedDisplayName, team.getDisplayName()); + assertEquals(expectedProfile, team.getProfile()); + TestUtils.assertEntityReferences(expectedUsers, team.getUsers()); + TestUtils.assertEntityReferences(expectedDefaultRoles, team.getDefaultRoles()); + validateEntityReferences(team.getOwns()); + } + + @Override + public Team validateGetWithDifferentFields(Team expectedTeam, boolean byName) throws HttpResponseException { + if (expectedTeam.getUsers() == null) { + UserResourceTest userResourceTest = new UserResourceTest(); + CreateUser create = userResourceTest.createRequest("user", "", "", null).withTeams(List.of(expectedTeam.getId())); + userResourceTest.createEntity(create, ADMIN_AUTH_HEADERS); + } + + String updatedBy = getPrincipalName(ADMIN_AUTH_HEADERS); + String fields = ""; + Team getTeam = + byName + ? getEntityByName(expectedTeam.getName(), fields, ADMIN_AUTH_HEADERS) + : getEntity(expectedTeam.getId(), null, fields, ADMIN_AUTH_HEADERS); + validateTeam(getTeam, expectedTeam.getDescription(), expectedTeam.getDisplayName(), null, null, null, updatedBy); + assertNull(getTeam.getOwns()); + + fields = "users,owns,profile,defaultRoles,owner"; + getTeam = + byName + ? getEntityByName(expectedTeam.getName(), fields, ADMIN_AUTH_HEADERS) + : getEntity(expectedTeam.getId(), fields, ADMIN_AUTH_HEADERS); + assertNotNull(getTeam.getProfile()); + validateEntityReferences(getTeam.getOwns()); + validateEntityReferences(getTeam.getUsers(), true); + validateEntityReferences(getTeam.getDefaultRoles()); + return getTeam; + } + + @Override + public CreateTeam createRequest(String name) { + return new CreateTeam().withName(name).withProfile(PROFILE); + } + + @Override + public Team beforeDeletion(TestInfo test, Team team) throws HttpResponseException { + LocationResourceTest locationResourceTest = new LocationResourceTest(); + EntityReference teamRef = new EntityReference().withId(team.getId()).withType("team"); + locationResourceTest.createEntity( + locationResourceTest.createRequest(getEntityName(test), null, null, teamRef), ADMIN_AUTH_HEADERS); + return team; + } + + @Override + public void validateCreatedEntity(Team team, CreateTeam createRequest, Map authHeaders) { + assertEquals(createRequest.getProfile(), team.getProfile()); + TestUtils.validateEntityReferences(team.getOwns()); + + List expectedUsers = new ArrayList<>(); + for (UUID userId : listOrEmpty(createRequest.getUsers())) { + expectedUsers.add(new EntityReference().withId(userId).withType(Entity.USER)); + } + expectedUsers = expectedUsers.isEmpty() ? null : expectedUsers; + TestUtils.assertEntityReferences(expectedUsers, team.getUsers()); + TestUtils.assertEntityReferenceIds(createRequest.getDefaultRoles(), team.getDefaultRoles()); + System.out.println("XXX " + team.getParents()); + TestUtils.assertEntityReferenceIds(createRequest.getParents(), team.getParents()); + TestUtils.assertEntityReferenceIds(createRequest.getChildren(), team.getChildren()); + TestUtils.assertEntityReferenceIds(createRequest.getPolicies(), team.getPolicies()); + } + + @Override + protected void validateDeletedEntity( + CreateTeam create, Team teamBeforeDeletion, Team teamAfterDeletion, Map authHeaders) + throws HttpResponseException { + super.validateDeletedEntity(create, teamBeforeDeletion, teamAfterDeletion, authHeaders); + + List expectedOwnedEntities = new ArrayList<>(); + for (EntityReference ref : listOrEmpty(teamBeforeDeletion.getOwns())) { + expectedOwnedEntities.add(new EntityReference().withId(ref.getId()).withType(Entity.TABLE)); + } + TestUtils.assertEntityReferences(expectedOwnedEntities, teamAfterDeletion.getOwns()); + } + + @Override + public void compareEntities(Team expected, Team updated, Map authHeaders) { + assertEquals(expected.getDisplayName(), updated.getDisplayName()); + assertEquals(expected.getProfile(), updated.getProfile()); + TestUtils.validateEntityReferences(updated.getOwns()); + + List expectedUsers = listOrEmpty(expected.getUsers()); + List actualUsers = listOrEmpty(updated.getUsers()); + TestUtils.assertEntityReferences(expectedUsers, actualUsers); + + List expectedDefaultRoles = listOrEmpty(expected.getDefaultRoles()); + List actualDefaultRoles = listOrEmpty(updated.getDefaultRoles()); + TestUtils.assertEntityReferences(expectedDefaultRoles, actualDefaultRoles); + } + + @Override + public void assertFieldChange(String fieldName, Object expected, Object actual) throws IOException { + if (expected == actual) { + return; + } + if (List.of("users", "defaultRoles", "parents", "children", "policies").contains(fieldName)) { + @SuppressWarnings("unchecked") + List expectedRefs = (List) expected; + List actualRefs = JsonUtils.readObjects(actual.toString(), EntityReference.class); + assertEntityReferences(expectedRefs, actualRefs); + } else { + assertCommonFieldChange(fieldName, expected, actual); + } + } + private Team createWithParents(String teamName, TeamType teamType, EntityReference... parents) throws HttpResponseException { List parentList = List.of(parents); @@ -488,192 +740,4 @@ public class TeamResourceTest extends EntityResourceTest { .withRoles(List.of(teamManager.getId())), ADMIN_AUTH_HEADERS); } - - @Test - void patch_isJoinable_200(TestInfo test) throws IOException { - CreateTeam create = - createRequest(getEntityName(test), "description", "displayName", null) - .withProfile(PROFILE) - .withIsJoinable(false); - Team team = createAndCheckEntity(create, ADMIN_AUTH_HEADERS); - - // patch the team with isJoinable set to true - String json = JsonUtils.pojoToJson(team); - team.setIsJoinable(true); - ChangeDescription change = getChangeDescription(team.getVersion()); - change.getFieldsUpdated().add(new FieldChange().withName("isJoinable").withOldValue(false).withNewValue(true)); - team = patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, UpdateType.MINOR_UPDATE, change); - - // set isJoinable to false and check - json = JsonUtils.pojoToJson(team); - team.setIsJoinable(false); - change = getChangeDescription(team.getVersion()); - change.getFieldsUpdated().add(new FieldChange().withName("isJoinable").withOldValue(true).withNewValue(false)); - patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, UpdateType.MINOR_UPDATE, change); - } - - @Test - void patch_deleteUserAndDefaultRoleFromTeam_200(TestInfo test) throws IOException { - UserResourceTest userResourceTest = new UserResourceTest(); - final int totalUsers = 20; - ArrayList users = new ArrayList<>(); - for (int i = 0; i < totalUsers; i++) { - User user = userResourceTest.createEntity(userResourceTest.createRequest(test, i), ADMIN_AUTH_HEADERS); - users.add(user.getId()); - } - - RoleResourceTest roleResourceTest = new RoleResourceTest(); - roleResourceTest.createRolesAndSetDefault(test, 5, 0); - List roles = roleResourceTest.listEntities(Map.of(), ADMIN_AUTH_HEADERS).getData(); - List rolesIds = roles.stream().map(Role::getId).collect(Collectors.toList()); - - CreateTeam create = - createRequest(getEntityName(test), "description", "displayName", null) - .withProfile(PROFILE) - .withUsers(users) - .withDefaultRoles(rolesIds); - Team team = createAndCheckEntity(create, ADMIN_AUTH_HEADERS); - - // Remove a user from the team using patch request - String json = JsonUtils.pojoToJson(team); - int removeUserIndex = new Random().nextInt(totalUsers); - EntityReference deletedUser = team.getUsers().get(removeUserIndex); - team.getUsers().remove(removeUserIndex); - ChangeDescription change = getChangeDescription(team.getVersion()); - change.getFieldsDeleted().add(new FieldChange().withName("users").withOldValue(Arrays.asList(deletedUser))); - team = patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, UpdateType.MINOR_UPDATE, change); - - // Remove a default role from the team using patch request - json = JsonUtils.pojoToJson(team); - int removeDefaultRoleIndex = new Random().nextInt(roles.size()); - EntityReference deletedRole = team.getDefaultRoles().get(removeDefaultRoleIndex); - team.getDefaultRoles().remove(removeDefaultRoleIndex); - change = getChangeDescription(team.getVersion()); - change.getFieldsDeleted().add(new FieldChange().withName("defaultRoles").withOldValue(Arrays.asList(deletedRole))); - patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, UpdateType.MINOR_UPDATE, change); - } - - private static void validateTeam( - Team team, - String expectedDescription, - String expectedDisplayName, - Profile expectedProfile, - List expectedUsers, - List expectedDefaultRoles, - String expectedUpdatedBy) { - assertListNotNull(team.getId(), team.getHref()); - assertEquals(expectedDescription, team.getDescription()); - assertEquals(expectedUpdatedBy, team.getUpdatedBy()); - assertEquals(expectedDisplayName, team.getDisplayName()); - assertEquals(expectedProfile, team.getProfile()); - TestUtils.assertEntityReferenceList(expectedUsers, team.getUsers()); - TestUtils.assertEntityReferenceList(expectedDefaultRoles, team.getDefaultRoles()); - validateEntityReferences(team.getOwns()); - } - - @Override - public Team validateGetWithDifferentFields(Team expectedTeam, boolean byName) throws HttpResponseException { - if (expectedTeam.getUsers() == null) { - UserResourceTest userResourceTest = new UserResourceTest(); - CreateUser create = userResourceTest.createRequest("user", "", "", null).withTeams(List.of(expectedTeam.getId())); - userResourceTest.createEntity(create, ADMIN_AUTH_HEADERS); - } - - String updatedBy = getPrincipalName(ADMIN_AUTH_HEADERS); - String fields = ""; - Team getTeam = - byName - ? getEntityByName(expectedTeam.getName(), fields, ADMIN_AUTH_HEADERS) - : getEntity(expectedTeam.getId(), null, fields, ADMIN_AUTH_HEADERS); - validateTeam(getTeam, expectedTeam.getDescription(), expectedTeam.getDisplayName(), null, null, null, updatedBy); - assertNull(getTeam.getOwns()); - - fields = "users,owns,profile,defaultRoles,owner"; - getTeam = - byName - ? getEntityByName(expectedTeam.getName(), fields, ADMIN_AUTH_HEADERS) - : getEntity(expectedTeam.getId(), fields, ADMIN_AUTH_HEADERS); - assertNotNull(getTeam.getProfile()); - validateEntityReferences(getTeam.getOwns()); - validateEntityReferences(getTeam.getUsers(), true); - validateEntityReferences(getTeam.getDefaultRoles()); - return getTeam; - } - - @Override - public CreateTeam createRequest(String name) { - return new CreateTeam().withName(name).withProfile(PROFILE); - } - - @Override - public Team beforeDeletion(TestInfo test, Team team) throws HttpResponseException { - LocationResourceTest locationResourceTest = new LocationResourceTest(); - EntityReference teamRef = new EntityReference().withId(team.getId()).withType("team"); - locationResourceTest.createEntity( - locationResourceTest.createRequest(getEntityName(test), null, null, teamRef), ADMIN_AUTH_HEADERS); - return team; - } - - @Override - public void validateCreatedEntity(Team team, CreateTeam createRequest, Map authHeaders) { - assertEquals(createRequest.getProfile(), team.getProfile()); - TestUtils.validateEntityReferences(team.getOwns()); - - List expectedUsers = new ArrayList<>(); - for (UUID userId : listOrEmpty(createRequest.getUsers())) { - expectedUsers.add(new EntityReference().withId(userId).withType(Entity.USER)); - } - expectedUsers = expectedUsers.isEmpty() ? null : expectedUsers; - TestUtils.assertEntityReferenceList(expectedUsers, team.getUsers()); - - List expectedDefaultRoles = new ArrayList<>(); - for (UUID roleId : listOrEmpty(createRequest.getDefaultRoles())) { - expectedDefaultRoles.add(new EntityReference().withId(roleId).withType(Entity.ROLE)); - } - expectedDefaultRoles = expectedDefaultRoles.isEmpty() ? null : expectedDefaultRoles; - TestUtils.assertEntityReferenceList(expectedDefaultRoles, team.getDefaultRoles()); - } - - @Override - protected void validateDeletedEntity( - CreateTeam create, Team teamBeforeDeletion, Team teamAfterDeletion, Map authHeaders) - throws HttpResponseException { - super.validateDeletedEntity(create, teamBeforeDeletion, teamAfterDeletion, authHeaders); - - List expectedOwnedEntities = new ArrayList<>(); - for (EntityReference ref : listOrEmpty(teamBeforeDeletion.getOwns())) { - expectedOwnedEntities.add(new EntityReference().withId(ref.getId()).withType(Entity.TABLE)); - } - TestUtils.assertEntityReferenceList(expectedOwnedEntities, teamAfterDeletion.getOwns()); - } - - @Override - public void compareEntities(Team expected, Team updated, Map authHeaders) { - assertEquals(expected.getDisplayName(), updated.getDisplayName()); - assertEquals(expected.getProfile(), updated.getProfile()); - TestUtils.validateEntityReferences(updated.getOwns()); - - List expectedUsers = listOrEmpty(expected.getUsers()); - List actualUsers = listOrEmpty(updated.getUsers()); - TestUtils.assertEntityReferenceList(expectedUsers, actualUsers); - - List expectedDefaultRoles = listOrEmpty(expected.getDefaultRoles()); - List actualDefaultRoles = listOrEmpty(updated.getDefaultRoles()); - TestUtils.assertEntityReferenceList(expectedDefaultRoles, actualDefaultRoles); - } - - @Override - public void assertFieldChange(String fieldName, Object expected, Object actual) throws IOException { - if (expected == actual) { - return; - } - if (List.of("users", "defaultRoles", "parents", "children").contains(fieldName)) { - @SuppressWarnings("unchecked") - List expectedRefs = (List) expected; - List actualRefs = JsonUtils.readObjects(actual.toString(), EntityReference.class); - assertEntityReferences(expectedRefs, actualRefs); - } else { - assertCommonFieldChange(fieldName, expected, actual); - } - } } diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/teams/UserResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/teams/UserResourceTest.java index 419dca358c9..276584e91f1 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/teams/UserResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/teams/UserResourceTest.java @@ -35,7 +35,7 @@ import static org.openmetadata.catalog.util.TestUtils.TEST_AUTH_HEADERS; import static org.openmetadata.catalog.util.TestUtils.TEST_USER_NAME; import static org.openmetadata.catalog.util.TestUtils.UpdateType.MINOR_UPDATE; import static org.openmetadata.catalog.util.TestUtils.assertDeleted; -import static org.openmetadata.catalog.util.TestUtils.assertEntityReferenceList; +import static org.openmetadata.catalog.util.TestUtils.assertEntityReferences; import static org.openmetadata.catalog.util.TestUtils.assertListNotNull; import static org.openmetadata.catalog.util.TestUtils.assertListNull; import static org.openmetadata.catalog.util.TestUtils.assertResponse; @@ -753,8 +753,8 @@ public class UserResourceTest extends EntityResourceTest { private void assertRoles( User user, List expectedRoles, List expectedInheritedRoles) { - assertEntityReferenceList(expectedRoles, user.getRoles()); - assertEntityReferenceList(expectedInheritedRoles, user.getInheritedRoles()); + TestUtils.assertEntityReferences(expectedRoles, user.getRoles()); + TestUtils.assertEntityReferences(expectedInheritedRoles, user.getInheritedRoles()); } @Override @@ -806,7 +806,7 @@ public class UserResourceTest extends EntityResourceTest { expectedOwnedEntities.add(new EntityReference().withId(ref.getId()).withType(Entity.TABLE)); } - TestUtils.assertEntityReferenceList(expectedOwnedEntities, userAfterDeletion.getOwns()); + TestUtils.assertEntityReferences(expectedOwnedEntities, userAfterDeletion.getOwns()); } @Override @@ -828,7 +828,7 @@ public class UserResourceTest extends EntityResourceTest { for (UUID teamId : listOrEmpty(createRequest.getTeams())) { expectedTeams.add(new EntityReference().withId(teamId).withType(Entity.TEAM)); } - TestUtils.assertEntityReferenceList(expectedTeams, user.getTeams()); + TestUtils.assertEntityReferences(expectedTeams, user.getTeams()); if (createRequest.getProfile() != null) { assertEquals(createRequest.getProfile(), user.getProfile()); @@ -843,8 +843,8 @@ public class UserResourceTest extends EntityResourceTest { assertEquals(expected.getIsBot(), expected.getIsBot()); assertEquals(expected.getIsAdmin(), expected.getIsAdmin()); - assertEntityReferenceList(expected.getRoles(), updated.getRoles()); - assertEntityReferenceList(expected.getTeams(), updated.getTeams()); + TestUtils.assertEntityReferences(expected.getRoles(), updated.getRoles()); + TestUtils.assertEntityReferences(expected.getTeams(), updated.getTeams()); if (expected.getProfile() != null) { assertEquals(expected.getProfile(), updated.getProfile()); diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/util/TestUtils.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/util/TestUtils.java index 6eb4485a9f9..016eac31542 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/util/TestUtils.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/util/TestUtils.java @@ -391,7 +391,22 @@ public final class TestUtils { } } - public static void assertEntityReferenceList(List expected, List actual) { + public static void assertEntityReferenceIds(List expected, List actual) { + if (expected == null && actual == null) { + return; + } + if (listOrEmpty(expected).isEmpty()) { + return; + } + for (UUID id : listOrEmpty(expected)) { + actual = listOrEmpty(actual); + assertEquals(expected.size(), actual.size()); + assertNotNull(actual.stream().filter(entity -> entity.getId().equals(id)).findAny().get()); + } + validateEntityReferences(actual); + } + + public static void assertEntityReferences(List expected, List actual) { if (expected == actual) { // Take care of both being null return; } diff --git a/ingestion-core/src/metadata/_version.py b/ingestion-core/src/metadata/_version.py index dd1a8293b19..370d1db9b13 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=3) +__version__ = Version("metadata", 0, 12, 0, dev=5) __all__ = ["__version__"]