mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-09-14 11:27:58 +00:00
Merge pull request #966 from open-metadata/issue965
Fixed 965 Add versioning API support for Team Entity
This commit is contained in:
commit
328db526a6
@ -247,13 +247,13 @@ public interface CollectionDAO {
|
||||
//
|
||||
@SqlQuery("SELECT toId, toEntity FROM entity_relationship " +
|
||||
"WHERE fromId = :fromId AND relation = :relation " +
|
||||
"ORDER BY fromId")
|
||||
"ORDER BY toId")
|
||||
@RegisterRowMapper(ToEntityReferenceMapper.class)
|
||||
List<EntityReference> findTo(@Bind("fromId") String fromId, @Bind("relation") int relation);
|
||||
|
||||
@SqlQuery("SELECT toId FROM entity_relationship " +
|
||||
"WHERE fromId = :fromId AND relation = :relation AND toEntity = :toEntity " +
|
||||
"ORDER BY fromId")
|
||||
"ORDER BY toId")
|
||||
List<String> findTo(@Bind("fromId") String fromId, @Bind("relation") int relation,
|
||||
@Bind("toEntity") String toEntity);
|
||||
|
||||
|
@ -31,9 +31,11 @@ import org.openmetadata.catalog.util.EntityUtil.Fields;
|
||||
import org.openmetadata.catalog.util.JsonUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@ -194,6 +196,9 @@ public class TeamRepository extends EntityRepository<Team> {
|
||||
@Override
|
||||
public Date getUpdatedAt() { return entity.getUpdatedAt(); }
|
||||
|
||||
@Override
|
||||
public URI getHref() { return entity.getHref(); }
|
||||
|
||||
@Override
|
||||
public EntityReference getEntityReference() {
|
||||
return new EntityReference().withId(getId()).withName(getFullyQualifiedName()).withDescription(getDescription())
|
||||
@ -226,6 +231,9 @@ public class TeamRepository extends EntityRepository<Team> {
|
||||
entity.setChangeDescription(changeDescription);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChangeDescription getChangeDescription() { return entity.getChangeDescription(); }
|
||||
|
||||
@Override
|
||||
public void setTags(List<TagLabel> tags) { }
|
||||
}
|
||||
@ -244,18 +252,26 @@ public class TeamRepository extends EntityRepository<Team> {
|
||||
if (updated.getEntity().getDeleted() != original.getEntity().getDeleted()) {
|
||||
throw new IllegalArgumentException(CatalogExceptionMessage.readOnlyAttribute("Team", "deleted"));
|
||||
}
|
||||
recordChange("profile", original.getEntity().getProfile(), updated.getEntity().getProfile());
|
||||
updateUsers(original.getEntity(), updated.getEntity());
|
||||
}
|
||||
|
||||
private void updateUsers(Team origTeam, Team updatedTeam) {
|
||||
List<EntityReference> origUsers = Optional.ofNullable(origTeam.getUsers()).orElse(Collections.emptyList());
|
||||
List<EntityReference> updatedUsers = Optional.ofNullable(updatedTeam.getUsers()).orElse(Collections.emptyList());
|
||||
|
||||
// Remove users from original and add users from updated
|
||||
dao.relationshipDAO().deleteFrom(origTeam.getId().toString(), Relationship.CONTAINS.ordinal(), "user");
|
||||
|
||||
for (EntityReference user : Optional.ofNullable(updatedTeam.getUsers()).orElse(Collections.emptyList())) {
|
||||
// Add relationships
|
||||
for (EntityReference user : updatedUsers) {
|
||||
dao.relationshipDAO().insert(updatedTeam.getId().toString(), user.getId().toString(),
|
||||
"team", "user", Relationship.CONTAINS.ordinal());
|
||||
}
|
||||
recordChange("users", origTeam.getUsers(), updatedTeam.getUsers());
|
||||
|
||||
// Sort by user Id as string (as done in the database)
|
||||
updatedUsers.sort(Comparator.comparing(entityReference -> entityReference.getId().toString()));
|
||||
origUsers.sort(Comparator.comparing(entityReference -> entityReference.getId().toString()));
|
||||
recordChange("users", origUsers.isEmpty() ? null : origUsers, updatedUsers.isEmpty() ? null : updatedUsers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -176,7 +176,6 @@ public class UserRepository extends EntityRepository<User> {
|
||||
private void assignTeams(User user, List<EntityReference> teams) {
|
||||
// Query - add team to the user
|
||||
teams = Optional.ofNullable(teams).orElse(Collections.emptyList());
|
||||
teams.sort(Comparator.comparing(EntityReference::getId)); // Sort team order to the query order
|
||||
for (EntityReference team : teams) {
|
||||
dao.relationshipDAO().insert(team.getId().toString(), user.getId().toString(),
|
||||
"team", "user", CONTAINS.ordinal());
|
||||
@ -301,19 +300,13 @@ public class UserRepository extends EntityRepository<User> {
|
||||
dao.relationshipDAO().deleteTo(origUser.getId().toString(), CONTAINS.ordinal(), "team");
|
||||
assignTeams(updatedUser, updatedUser.getTeams());
|
||||
|
||||
List<EntityReference> origTeams = origUser.getTeams();
|
||||
List<EntityReference> updatedTeams = updatedUser.getTeams();
|
||||
if (origTeams == null || origTeams.isEmpty()) {
|
||||
origTeams = null;
|
||||
} else {
|
||||
origTeams.sort(Comparator.comparing(EntityReference::getId));
|
||||
}
|
||||
if (updatedTeams == null || updatedTeams.isEmpty()) {
|
||||
updatedTeams = null;
|
||||
} else {
|
||||
updatedTeams.sort(Comparator.comparing(EntityReference::getId));
|
||||
}
|
||||
recordChange("teams", origTeams, updatedTeams);
|
||||
List<EntityReference> origTeams = Optional.ofNullable(origUser.getTeams()).orElse(Collections.emptyList());
|
||||
List<EntityReference> updatedTeams = Optional.ofNullable(updatedUser.getTeams()).orElse(Collections.emptyList());
|
||||
|
||||
// Sort by team Id as string (as done in the database)
|
||||
origTeams.sort(Comparator.comparing(entityReference -> entityReference.getId().toString()));
|
||||
updatedTeams.sort(Comparator.comparing(entityReference -> entityReference.getId().toString()));
|
||||
recordChange("teams", origTeams.isEmpty() ? null : origTeams, updatedTeams.isEmpty() ? null : updatedTeams);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ import org.openmetadata.catalog.jdbi3.TeamRepository;
|
||||
import org.openmetadata.catalog.resources.Collection;
|
||||
import org.openmetadata.catalog.security.CatalogAuthorizer;
|
||||
import org.openmetadata.catalog.security.SecurityUtil;
|
||||
import org.openmetadata.catalog.type.EntityHistory;
|
||||
import org.openmetadata.catalog.type.EntityReference;
|
||||
import org.openmetadata.catalog.util.EntityUtil;
|
||||
import org.openmetadata.catalog.util.RestUtil;
|
||||
@ -48,6 +49,7 @@ import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
@ -106,7 +108,7 @@ public class TeamResource {
|
||||
}
|
||||
}
|
||||
|
||||
private static final String FIELDS = "profile,users,owns";
|
||||
public static final String FIELDS = "profile,users,owns";
|
||||
public static final List<String> FIELD_LIST = Arrays.asList(FIELDS.replaceAll(" ", "")
|
||||
.split(","));
|
||||
@GET
|
||||
@ -150,6 +152,22 @@ public class TeamResource {
|
||||
return teams;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/{id}/versions")
|
||||
@Operation(summary = "List team versions", tags = "teams",
|
||||
description = "Get a list of all the versions of a team identified by `id`",
|
||||
responses = {@ApiResponse(responseCode = "200", description = "List of team versions",
|
||||
content = @Content(mediaType = "application/json",
|
||||
schema = @Schema(implementation = EntityHistory.class)))
|
||||
})
|
||||
public EntityHistory listVersions(@Context UriInfo uriInfo,
|
||||
@Context SecurityContext securityContext,
|
||||
@Parameter(description = "team Id", schema = @Schema(type = "string"))
|
||||
@PathParam("id") String id)
|
||||
throws IOException, ParseException, GeneralSecurityException {
|
||||
return dao.listVersions(id);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Valid
|
||||
@Path("/{id}")
|
||||
@ -192,6 +210,27 @@ public class TeamResource {
|
||||
return addHref(uriInfo, dao.getByName(name, fields));
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/{id}/versions/{version}")
|
||||
@Operation(summary = "Get a version of the team", tags = "teams",
|
||||
description = "Get a version of the team by given `id`",
|
||||
responses = {
|
||||
@ApiResponse(responseCode = "200", description = "team",
|
||||
content = @Content(mediaType = "application/json",
|
||||
schema = @Schema(implementation = Team.class))),
|
||||
@ApiResponse(responseCode = "404", description = "Team for instance {id} and version {version} is " +
|
||||
"not found")
|
||||
})
|
||||
public Team getVersion(@Context UriInfo uriInfo,
|
||||
@Context SecurityContext securityContext,
|
||||
@Parameter(description = "Team Id", schema = @Schema(type = "string"))
|
||||
@PathParam("id") String id,
|
||||
@Parameter(description = "Team version number in the form `major`.`minor`",
|
||||
schema = @Schema(type = "string", example = "0.1 or 1.1"))
|
||||
@PathParam("version") String version) throws IOException, ParseException {
|
||||
return dao.getVersion(id, version);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Operation(summary = "Create a team", tags = "teams",
|
||||
description = "Create a new team.",
|
||||
@ -205,15 +244,30 @@ public class TeamResource {
|
||||
@Context SecurityContext securityContext,
|
||||
@Valid CreateTeam ct) throws IOException, ParseException {
|
||||
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
|
||||
Team team = new Team().withId(UUID.randomUUID()).withName(ct.getName()).withDescription(ct.getDescription())
|
||||
.withDisplayName(ct.getDisplayName()).withProfile(ct.getProfile())
|
||||
.withUpdatedBy(securityContext.getUserPrincipal().getName())
|
||||
.withUpdatedAt(new Date())
|
||||
.withUsers(dao.getUsers(ct.getUsers()));
|
||||
Team team = getTeam(ct, securityContext);
|
||||
addHref(uriInfo, dao.create(team));
|
||||
return Response.created(team.getHref()).entity(team).build();
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Operation(summary = "Create or Update a team", tags = "teams",
|
||||
description = "Create or Update a team.",
|
||||
responses = {
|
||||
@ApiResponse(responseCode = "200", description = "The team ",
|
||||
content = @Content(mediaType = "application/json",
|
||||
schema = @Schema(implementation = CreateTeam.class))),
|
||||
@ApiResponse(responseCode = "400", description = "Bad request")
|
||||
})
|
||||
public Response createOrUpdateTeam(@Context UriInfo uriInfo,
|
||||
@Context SecurityContext securityContext,
|
||||
@Valid CreateTeam ct) throws IOException, ParseException {
|
||||
SecurityUtil.checkAdminOrBotRole(authorizer, securityContext);
|
||||
Team team = getTeam(ct, securityContext);
|
||||
RestUtil.PutResponse<Team> response = dao.createOrUpdate(team);
|
||||
team = addHref(uriInfo, response.getEntity());
|
||||
return Response.status(response.getStatus()).entity(team).build();
|
||||
}
|
||||
|
||||
@PATCH
|
||||
@Valid
|
||||
@Path("/{id}")
|
||||
@ -252,4 +306,12 @@ public class TeamResource {
|
||||
dao.delete(UUID.fromString(id));
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
private Team getTeam(CreateTeam ct, SecurityContext securityContext) throws IOException {
|
||||
return new Team().withId(UUID.randomUUID()).withName(ct.getName()).withDescription(ct.getDescription())
|
||||
.withDisplayName(ct.getDisplayName()).withProfile(ct.getProfile())
|
||||
.withUpdatedBy(securityContext.getUserPrincipal().getName())
|
||||
.withUpdatedAt(new Date())
|
||||
.withUsers(dao.getUsers(ct.getUsers()));
|
||||
}
|
||||
}
|
@ -176,7 +176,6 @@ public class UserResource {
|
||||
return dao.listVersions(id);
|
||||
}
|
||||
|
||||
|
||||
@GET
|
||||
@Valid
|
||||
@Path("/{id}")
|
||||
|
@ -55,7 +55,8 @@
|
||||
},
|
||||
"users" : {
|
||||
"description": "Users that are part of the team.",
|
||||
"$ref": "../../type/entityReference.json#/definitions/entityReferenceList"
|
||||
"$ref": "../../type/entityReference.json#/definitions/entityReferenceList",
|
||||
"default": null
|
||||
},
|
||||
"owns" : {
|
||||
"description": "List of entities owned by the team.",
|
||||
|
@ -26,15 +26,18 @@ import org.openmetadata.catalog.api.teams.CreateTeam;
|
||||
import org.openmetadata.catalog.entity.teams.Team;
|
||||
import org.openmetadata.catalog.entity.teams.User;
|
||||
import org.openmetadata.catalog.exception.CatalogExceptionMessage;
|
||||
import org.openmetadata.catalog.jdbi3.TeamRepository.TeamEntityInterface;
|
||||
import org.openmetadata.catalog.jdbi3.UserRepository.UserEntityInterface;
|
||||
import org.openmetadata.catalog.resources.EntityResourceTest;
|
||||
import org.openmetadata.catalog.resources.databases.TableResourceTest;
|
||||
import org.openmetadata.catalog.resources.teams.TeamResource.TeamList;
|
||||
import org.openmetadata.catalog.type.ChangeDescription;
|
||||
import org.openmetadata.catalog.type.EntityReference;
|
||||
import org.openmetadata.catalog.type.ImageList;
|
||||
import org.openmetadata.catalog.type.Profile;
|
||||
import org.openmetadata.catalog.util.EntityInterface;
|
||||
import org.openmetadata.catalog.util.JsonUtils;
|
||||
import org.openmetadata.catalog.util.TestUtils;
|
||||
import org.openmetadata.catalog.util.TestUtils.UpdateType;
|
||||
import org.openmetadata.common.utils.JsonSchemaUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -45,6 +48,7 @@ import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@ -62,17 +66,20 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.openmetadata.catalog.exception.CatalogExceptionMessage.entityNotFound;
|
||||
import static org.openmetadata.catalog.resources.teams.UserResourceTest.createUser;
|
||||
import static org.openmetadata.catalog.util.TestUtils.UpdateType.MINOR_UPDATE;
|
||||
import static org.openmetadata.catalog.util.TestUtils.UpdateType.NO_CHANGE;
|
||||
import static org.openmetadata.catalog.util.TestUtils.adminAuthHeaders;
|
||||
import static org.openmetadata.catalog.util.TestUtils.assertEntityPagination;
|
||||
import static org.openmetadata.catalog.util.TestUtils.assertResponse;
|
||||
import static org.openmetadata.catalog.util.TestUtils.authHeaders;
|
||||
import static org.openmetadata.catalog.util.TestUtils.validateEntityReference;
|
||||
|
||||
public class TeamResourceTest extends CatalogApplicationTest {
|
||||
public class TeamResourceTest extends EntityResourceTest<Team> {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TeamResourceTest.class);
|
||||
final Profile PROFILE = new Profile().withImages(new ImageList().withImage(URI.create("http://image.com")));
|
||||
|
||||
public TeamResourceTest() {
|
||||
super(Team.class, "teams", TeamResource.FIELDS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void post_teamWithLongName_400_badRequest(TestInfo test) {
|
||||
// Create team with mandatory name field empty
|
||||
@ -102,19 +109,19 @@ public class TeamResourceTest extends CatalogApplicationTest {
|
||||
public void post_validTeams_as_admin_200_OK(TestInfo test) throws HttpResponseException {
|
||||
// Create team with different optional fields
|
||||
CreateTeam create = create(test, 1);
|
||||
createAndCheckTeam(create, adminAuthHeaders());
|
||||
createAndCheckEntity(create, adminAuthHeaders());
|
||||
|
||||
create = create(test, 2).withDisplayName("displayName");
|
||||
createAndCheckTeam(create, adminAuthHeaders());
|
||||
createAndCheckEntity(create, adminAuthHeaders());
|
||||
|
||||
create = create(test, 3).withDescription("description");
|
||||
createAndCheckTeam(create, adminAuthHeaders());
|
||||
createAndCheckEntity(create, adminAuthHeaders());
|
||||
|
||||
create = create(test, 4).withProfile(PROFILE);
|
||||
createAndCheckTeam(create, adminAuthHeaders());
|
||||
createAndCheckEntity(create, adminAuthHeaders());
|
||||
|
||||
create = create(test, 5).withDisplayName("displayName").withDescription("description").withProfile(PROFILE);
|
||||
createAndCheckTeam(create, adminAuthHeaders());
|
||||
createAndCheckEntity(create, adminAuthHeaders());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -122,7 +129,7 @@ public class TeamResourceTest extends CatalogApplicationTest {
|
||||
// Create team with different optional fields
|
||||
Map<String, String> authHeaders = authHeaders("test@open-metadata.org");
|
||||
CreateTeam create = create(test, 1);
|
||||
HttpResponseException exception = assertThrows(HttpResponseException.class, () -> createAndCheckTeam(create,
|
||||
HttpResponseException exception = assertThrows(HttpResponseException.class, () -> createAndCheckEntity(create,
|
||||
authHeaders));
|
||||
assertResponse(exception, FORBIDDEN, "Principal: CatalogPrincipal{name='test'} is not admin");
|
||||
}
|
||||
@ -137,7 +144,7 @@ public class TeamResourceTest extends CatalogApplicationTest {
|
||||
List<UUID> users = Arrays.asList(user1.getId(), user2.getId());
|
||||
CreateTeam create = create(test).withDisplayName("displayName").withDescription("description")
|
||||
.withProfile(PROFILE).withUsers(users);
|
||||
Team team = createAndCheckTeam(create, adminAuthHeaders());
|
||||
Team team = createAndCheckEntity(create, adminAuthHeaders());
|
||||
|
||||
// Make sure the user entity has relationship to the team
|
||||
user1 = UserResourceTest.getUser(user1.getId(), "teams", authHeaders("test@open-metadata.org"));
|
||||
@ -293,7 +300,7 @@ public class TeamResourceTest extends CatalogApplicationTest {
|
||||
User user1 = createUser(UserResourceTest.create(test, 1), adminAuthHeaders());
|
||||
List<UUID> users = Collections.singletonList(user1.getId());
|
||||
CreateTeam create = create(test).withUsers(users);
|
||||
Team team = createAndCheckTeam(create, adminAuthHeaders());
|
||||
Team team = createAndCheckEntity(create, adminAuthHeaders());
|
||||
deleteTeam(team.getId(), adminAuthHeaders());
|
||||
|
||||
// Make sure team is no longer there
|
||||
@ -312,7 +319,7 @@ public class TeamResourceTest extends CatalogApplicationTest {
|
||||
authHeaders("test@open-metadata.org"));
|
||||
List<UUID> users = Collections.singletonList(user1.getId());
|
||||
CreateTeam create = create(test).withUsers(users);
|
||||
Team team = createAndCheckTeam(create, adminAuthHeaders());
|
||||
Team team = createAndCheckEntity(create, adminAuthHeaders());
|
||||
HttpResponseException exception = assertThrows(HttpResponseException.class, () ->
|
||||
deleteTeam(team.getId(), authHeaders("test@open-metadata.org")));
|
||||
assertResponse(exception, FORBIDDEN, "Principal: CatalogPrincipal{name='test'} is not admin");
|
||||
@ -340,7 +347,9 @@ public class TeamResourceTest extends CatalogApplicationTest {
|
||||
@Test
|
||||
public void patch_teamAttributes_as_admin_200_ok(TestInfo test)
|
||||
throws HttpResponseException, JsonProcessingException {
|
||||
//
|
||||
// Create table without any attributes
|
||||
//
|
||||
Team team = createTeam(create(test), adminAuthHeaders());
|
||||
assertNull(team.getDisplayName());
|
||||
assertNull(team.getDescription());
|
||||
@ -356,80 +365,50 @@ public class TeamResourceTest extends CatalogApplicationTest {
|
||||
new UserEntityInterface(user2).getEntityReference());
|
||||
Profile profile = new Profile().withImages(new ImageList().withImage(URI.create("http://image.com")));
|
||||
|
||||
//
|
||||
// Add previously absent attributes
|
||||
team = patchTeamAttributesAndCheck(team, "displayName", "description", profile, users,
|
||||
adminAuthHeaders(), MINOR_UPDATE);
|
||||
//
|
||||
String originalJson = JsonUtils.pojoToJson(team);
|
||||
team.withDisplayName("displayName").withDescription("description").withProfile(profile).withUsers(users);
|
||||
ChangeDescription change = getChangeDescription(team.getVersion())
|
||||
.withFieldsAdded(Arrays.asList("displayName", "description", "profile", "users"));
|
||||
team = patchEntityAndCheck(team, originalJson, adminAuthHeaders(), MINOR_UPDATE, change);
|
||||
team.getUsers().get(0).setHref(null);
|
||||
team.getUsers().get(1).setHref(null);
|
||||
|
||||
//
|
||||
// Replace the attributes
|
||||
//
|
||||
users = Arrays.asList(new UserEntityInterface(user1).getEntityReference(),
|
||||
new UserEntityInterface(user3).getEntityReference()); // user2 dropped and user3 is added
|
||||
profile = new Profile().withImages(new ImageList().withImage(URI.create("http://image1.com")));
|
||||
team = patchTeamAttributesAndCheck(team, "displayName1", "description1", profile, users,
|
||||
adminAuthHeaders(), MINOR_UPDATE);
|
||||
|
||||
originalJson = JsonUtils.pojoToJson(team);
|
||||
team.withDisplayName("displayName1").withDescription("description1").withProfile(profile).withUsers(users);
|
||||
change = getChangeDescription(team.getVersion())
|
||||
.withFieldsUpdated(Arrays.asList("displayName", "description", "profile", "users"));
|
||||
team = patchEntityAndCheck(team, originalJson, adminAuthHeaders(), MINOR_UPDATE, change);
|
||||
|
||||
// Remove the attributes
|
||||
patchTeamAttributesAndCheck(team, null, null, null, null,
|
||||
adminAuthHeaders(), MINOR_UPDATE);
|
||||
originalJson = JsonUtils.pojoToJson(team);
|
||||
team.withDisplayName(null).withDescription(null).withProfile(null).withUsers(null);
|
||||
change = getChangeDescription(team.getVersion())
|
||||
.withFieldsDeleted(Arrays.asList("displayName", "description", "profile", "users"));
|
||||
patchEntityAndCheck(team, originalJson, adminAuthHeaders(), MINOR_UPDATE, change);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patch_teamAttributes_as_non_admin_401(TestInfo test) throws HttpResponseException {
|
||||
public void patch_teamAttributes_as_non_admin_403(TestInfo test) throws HttpResponseException,
|
||||
JsonProcessingException {
|
||||
// Create table without any attributes
|
||||
Team team = createTeam(create(test), adminAuthHeaders());
|
||||
assertNull(team.getDisplayName());
|
||||
assertNull(team.getDescription());
|
||||
assertNull(team.getProfile());
|
||||
assertNull(team.getDeleted());
|
||||
assertNull(team.getUsers());
|
||||
|
||||
User user1 = createUser(UserResourceTest.create(test, 1), authHeaders("test@open-metadata.org"));
|
||||
User user2 = createUser(UserResourceTest.create(test, 2), authHeaders("test@open-metadata.org"));
|
||||
User user3 = createUser(UserResourceTest.create(test, 3), authHeaders("test@open-metadata.org"));
|
||||
|
||||
List<EntityReference> users = Arrays.asList(new UserEntityInterface(user1).getEntityReference(),
|
||||
new UserEntityInterface(user2).getEntityReference(),
|
||||
new UserEntityInterface(user3).getEntityReference());
|
||||
|
||||
Profile profile = new Profile().withImages(new ImageList().withImage(URI.create("http://image.com")));
|
||||
|
||||
// Patching as a non-admin should is disallowed
|
||||
String originalJson = JsonUtils.pojoToJson(team);
|
||||
team.setDisplayName("newDisplayName");
|
||||
HttpResponseException exception = assertThrows(HttpResponseException.class, () ->
|
||||
patchTeamAttributesAndCheck(team, "displayName", "description", profile, users,
|
||||
authHeaders("test@open-metadata.org"), NO_CHANGE));
|
||||
patchTeam(team.getId(), originalJson, team, authHeaders("test@open-metadata.org")));
|
||||
assertResponse(exception, FORBIDDEN, "Principal: CatalogPrincipal{name='test'} is not admin");
|
||||
}
|
||||
// @Test
|
||||
// public void patch_updateInvalidUsers_404_notFound(TestInfo test) throws HttpResponseException {
|
||||
// CreateTeam create = create(test);
|
||||
// Team team = createAndCheckTeam(create);
|
||||
//
|
||||
// // User patch to add team to user relationship to an invalid user
|
||||
// List<UUID> users = Collections.singletonList(UUID.randomUUID() /* invalid userId */);
|
||||
// UpdateTeam update = new UpdateTeam().withUsers(users);
|
||||
// HttpResponseException exception = assertThrows(HttpResponseException.class, () ->
|
||||
// updateTeam(team.getId(), update));
|
||||
// assertEquals(Response.Status.NOT_FOUND.getStatusCode(), exception.getStatusCode());
|
||||
// }
|
||||
|
||||
public static Team createAndCheckTeam(CreateTeam create, Map<String, String> authHeaders)
|
||||
throws HttpResponseException {
|
||||
String updatedBy = TestUtils.getPrincipal(authHeaders);
|
||||
Team team = createTeam(create, authHeaders);
|
||||
assertEquals(0.1, team.getVersion());
|
||||
List<EntityReference> expectedUsers = new ArrayList<>();
|
||||
for (UUID teamId : Optional.ofNullable(create.getUsers()).orElse(Collections.emptyList())) {
|
||||
expectedUsers.add(new EntityReference().withId(teamId).withType(Entity.USER));
|
||||
}
|
||||
|
||||
assertEquals(team.getName(), create.getName());
|
||||
validateTeam(team, create.getDescription(), create.getDisplayName(), create.getProfile(), expectedUsers, updatedBy);
|
||||
|
||||
// Get the newly created team and validate it
|
||||
Team getTeam = getTeam(team.getId(), "profile,users", authHeaders);
|
||||
assertEquals(team.getName(), create.getName());
|
||||
validateTeam(getTeam, create.getDescription(), create.getDisplayName(), create.getProfile(), expectedUsers,
|
||||
updatedBy);
|
||||
return team;
|
||||
}
|
||||
|
||||
public static Team createTeam(CreateTeam create, Map<String, String> authHeaders) throws HttpResponseException {
|
||||
return TestUtils.post(CatalogApplicationTest.getResource("teams"), create, Team.class, authHeaders);
|
||||
@ -521,30 +500,6 @@ public class TeamResourceTest extends CatalogApplicationTest {
|
||||
return patchTeam(updated.getId(), originalJson, updated, authHeaders);
|
||||
}
|
||||
|
||||
private Team patchTeamAttributesAndCheck(Team before, String displayName, String description, Profile profile,
|
||||
List<EntityReference> users, Map<String, String> authHeaders, UpdateType updateType)
|
||||
throws JsonProcessingException, HttpResponseException {
|
||||
String updatedBy = TestUtils.getPrincipal(authHeaders);
|
||||
Optional.ofNullable(before.getUsers()).orElse(Collections.emptyList()).forEach(t -> t.setHref(null)); // Remove href
|
||||
String tableJson = JsonUtils.pojoToJson(before);
|
||||
|
||||
// Update the table attributes
|
||||
before.setDisplayName(displayName);
|
||||
before.setDescription(description);
|
||||
before.setProfile(profile);
|
||||
before.setUsers(users);
|
||||
|
||||
// Validate information returned in patch response has the updates
|
||||
Team updatedTeam = patchTeam(tableJson, before, authHeaders);
|
||||
validateTeam(updatedTeam, description, displayName, profile, users, updatedBy);
|
||||
TestUtils.validateUpdate(before.getVersion(), updatedTeam.getVersion(), updateType);
|
||||
|
||||
// GET the table and Validate information returned
|
||||
Team getTeam = getTeam(before.getId(), "users,profile", authHeaders);
|
||||
validateTeam(getTeam, description, displayName, profile, users, updatedBy);
|
||||
return getTeam;
|
||||
}
|
||||
|
||||
public void deleteTeam(UUID id, Map<String, String> authHeaders) throws HttpResponseException {
|
||||
TestUtils.delete(CatalogApplicationTest.getResource("teams/" + id), authHeaders);
|
||||
}
|
||||
@ -560,4 +515,71 @@ public class TeamResourceTest extends CatalogApplicationTest {
|
||||
public static String getTeamName(TestInfo test) {
|
||||
return String.format("team_%s", test.getDisplayName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createRequest(TestInfo test, String description, String displayName, EntityReference owner) {
|
||||
return create(test).withDescription(description).withDisplayName(displayName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateCreatedEntity(Team team, Object request, Map<String, String> authHeaders) {
|
||||
CreateTeam createRequest = (CreateTeam) request;
|
||||
validateCommonEntityFields(getEntityInterface(team), createRequest.getDescription(),
|
||||
TestUtils.getPrincipal(authHeaders), null);
|
||||
|
||||
assertEquals(createRequest.getDisplayName(), team.getDisplayName());
|
||||
assertEquals(createRequest.getProfile(), team.getProfile());
|
||||
|
||||
List<EntityReference> expectedUsers = new ArrayList<>();
|
||||
for (UUID teamId : Optional.ofNullable(createRequest.getUsers()).orElse(Collections.emptyList())) {
|
||||
expectedUsers.add(new EntityReference().withId(teamId).withType(Entity.USER));
|
||||
}
|
||||
List<EntityReference> actualUsers = Optional.ofNullable(team.getUsers()).orElse(Collections.emptyList());
|
||||
if (!expectedUsers.isEmpty()) {
|
||||
assertEquals(expectedUsers.size(), actualUsers.size());
|
||||
for (EntityReference user : actualUsers) {
|
||||
TestUtils.validateEntityReference(user);
|
||||
boolean foundUser = false;
|
||||
for (EntityReference expectedEntity : expectedUsers) {
|
||||
if (expectedEntity.getId().equals(user.getId())) {
|
||||
foundUser = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertTrue(foundUser);
|
||||
}
|
||||
}
|
||||
TestUtils.validateEntityReference(team.getOwns());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateUpdatedEntity(Team updatedEntity, Object request, Map<String, String> authHeaders) {
|
||||
validateCreatedEntity(updatedEntity, request, authHeaders);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validatePatchedEntity(Team expected, Team updated, Map<String, String> authHeaders) {
|
||||
validateCommonEntityFields(getEntityInterface(updated), expected.getDescription(),
|
||||
TestUtils.getPrincipal(authHeaders), null);
|
||||
|
||||
assertEquals(expected.getDisplayName(), updated.getDisplayName());
|
||||
assertEquals(expected.getProfile(), updated.getProfile());
|
||||
|
||||
List<EntityReference> expectedUsers = Optional.ofNullable(expected.getUsers()).orElse(Collections.emptyList());
|
||||
List<EntityReference> actualUsers = Optional.ofNullable(updated.getUsers()).orElse(Collections.emptyList());
|
||||
actualUsers.forEach(TestUtils::validateEntityReference);
|
||||
actualUsers.forEach(user -> user.setHref(null));
|
||||
|
||||
// Note ordering is same as server side ordering by ID as string
|
||||
// Patch requests work only if the same ordering of users on the server side
|
||||
actualUsers.sort(Comparator.comparing(entityReference -> entityReference.getId().toString()));
|
||||
expectedUsers.sort(Comparator.comparing(entityReference -> entityReference.getId().toString()));
|
||||
assertEquals(expectedUsers, actualUsers);
|
||||
TestUtils.validateEntityReference(updated.getOwns());
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityInterface<Team> getEntityInterface(Team entity) {
|
||||
return new TeamEntityInterface(entity);
|
||||
}
|
||||
}
|
||||
|
@ -448,7 +448,9 @@ public class UserResourceTest extends EntityResourceTest<User> {
|
||||
.withFieldsUpdated(Arrays.asList("teams", "timezone", "profile", "isBot"));
|
||||
user = patchEntityAndCheck(user, origJson, adminAuthHeaders(), MINOR_UPDATE, change);
|
||||
|
||||
//
|
||||
// Remove the attributes
|
||||
//
|
||||
origJson = JsonUtils.pojoToJson(user);
|
||||
user.withTeams(null).withTimezone(null).withDisplayName(null).withProfile(null)
|
||||
.withIsBot(null).withIsAdmin(false);
|
||||
@ -654,8 +656,10 @@ public class UserResourceTest extends EntityResourceTest<User> {
|
||||
|
||||
updatedTeams.forEach(TestUtils::validateEntityReference);
|
||||
|
||||
expectedTeams.sort(Comparator.comparing(EntityReference::getName));
|
||||
updatedTeams.sort(Comparator.comparing(EntityReference::getName));
|
||||
// Note ordering is same as server side ordering by ID as string
|
||||
// Patch requests work only if the same ordering of users on the server side
|
||||
expectedTeams.sort(Comparator.comparing(entityReference -> entityReference.getId().toString()));
|
||||
updatedTeams.sort(Comparator.comparing(entityReference -> entityReference.getId().toString()));
|
||||
updatedTeams.forEach(t -> t.setHref(null));
|
||||
assertEquals(expectedTeams, updatedTeams);
|
||||
if (expected.getProfile() != null) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user