Fix #5382 Backend: Update timestamp of thread for any reaction (#5443)

This commit is contained in:
Vivek Ratnavel Subramanian 2022-06-13 23:12:20 -07:00 committed by GitHub
parent ffcc88330c
commit d65c97c4e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 59 additions and 16 deletions

View File

@ -34,5 +34,5 @@ public class AuthConfiguration {
@Getter @Setter private CustomOIDCSSOClientConfig customOidc;
@Getter @Setter private OpenMetadataJWTClientConfig openMetadataJWT;
@Getter @Setter private OpenMetadataJWTClientConfig openmetadata;
}

View File

@ -19,6 +19,7 @@ import static org.openmetadata.catalog.type.EventType.ENTITY_UPDATED;
import static org.openmetadata.common.utils.CommonUtil.listOrEmpty;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@ -233,6 +234,7 @@ public class ChangeEventHandler implements EventHandler {
.withThreadTs(System.currentTimeMillis())
.withCreatedBy(entityInterface.getUpdatedBy())
.withAbout(about.getLinkString())
.withReactions(Collections.emptyList())
.withUpdatedBy(entityInterface.getUpdatedBy())
.withUpdatedAt(System.currentTimeMillis())
.withMessage(message);
@ -265,6 +267,7 @@ public class ChangeEventHandler implements EventHandler {
.withThreadTs(System.currentTimeMillis())
.withCreatedBy(loggedInUserName)
.withAbout(linkString)
.withReactions(Collections.emptyList())
.withUpdatedBy(loggedInUserName)
.withUpdatedAt(System.currentTimeMillis())
.withMessage(message);

View File

@ -382,8 +382,19 @@ public class FeedRepository {
return new ResultList<>(threads, beforeCursor, afterCursor, total);
}
private void storeReactions(Thread thread, String user) {
// Reactions are captured at the thread level. If the user reacted to a post of a thread,
// it will still be tracked as "user reacted to thread" since this will only be used to filter
// threads in the activity feed. Actual reactions are stored in thread.json or post.json itself.
// Multiple reactions by the same user on same thread or post is handled by
// field relationship table constraint (primary key)
dao.fieldRelationshipDAO()
.insert(user, thread.getId().toString(), Entity.USER, Entity.THREAD, Relationship.REACTED_TO.ordinal(), null);
}
@Transaction
public final PatchResponse<Post> patchPost(Thread thread, Post post, JsonPatch patch) throws IOException {
public final PatchResponse<Post> patchPost(Thread thread, Post post, String user, JsonPatch patch)
throws IOException {
// Apply JSON patch to the original post to get the updated post
Post updated = JsonUtils.applyPatch(post, patch, Post.class);
@ -396,13 +407,24 @@ public class FeedRepository {
List<Post> posts = thread.getPosts();
posts = posts.stream().filter(p -> !p.getId().equals(post.getId())).collect(Collectors.toList());
posts.add(updated);
thread.setPosts(posts);
thread.withPosts(posts).withUpdatedAt(System.currentTimeMillis()).withUpdatedBy(user);
if (!updated.getReactions().isEmpty()) {
updated
.getReactions()
.forEach(
reaction -> {
storeReactions(thread, reaction.getUser().getName());
});
}
String change = patchUpdate(thread, post, updated) ? RestUtil.ENTITY_UPDATED : RestUtil.ENTITY_NO_CHANGE;
return new PatchResponse<>(Status.OK, updated, change);
}
@Transaction
public final PatchResponse<Thread> patch(UriInfo uriInfo, UUID id, String user, JsonPatch patch) throws IOException {
public final PatchResponse<Thread> patchThread(UriInfo uriInfo, UUID id, String user, JsonPatch patch)
throws IOException {
// Get all the fields in the original thread that can be updated during PATCH operation
Thread original = get(id.toString());
@ -413,6 +435,15 @@ public class FeedRepository {
restorePatchAttributes(original, updated);
if (!updated.getReactions().isEmpty()) {
updated
.getReactions()
.forEach(
reaction -> {
storeReactions(updated, reaction.getUser().getName());
});
}
// Update the attributes
String change = patchUpdate(original, updated) ? RestUtil.ENTITY_UPDATED : RestUtil.ENTITY_NO_CHANGE;
Thread updatedHref = FeedResource.addHref(uriInfo, updated);

View File

@ -225,7 +225,7 @@ public class FeedResource {
JsonPatch patch)
throws IOException {
PatchResponse<Thread> response =
dao.patch(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
dao.patchThread(uriInfo, UUID.fromString(id), securityContext.getUserPrincipal().getName(), patch);
return response.toResponse();
}
@ -333,7 +333,7 @@ public class FeedResource {
Thread thread = dao.get(threadId);
Post post = dao.getPostById(thread, postId);
PatchResponse<Post> response = dao.patchPost(thread, post, patch);
PatchResponse<Post> response = dao.patchPost(thread, post, securityContext.getUserPrincipal().getName(), patch);
return response.toResponse();
}

View File

@ -85,7 +85,7 @@ public final class OpenMetadataClientSecurityUtil {
openMetadataServerConnection.setSecurityConfig(customOIDCSSOClientConfig);
break;
case OPENMETADATA:
OpenMetadataJWTClientConfig openMetadataJWTClientConfig = authConfig.getOpenMetadataJWT();
OpenMetadataJWTClientConfig openMetadataJWTClientConfig = authConfig.getOpenmetadata();
checkAuthConfig(openMetadataJWTClientConfig, authProvider);
checkRequiredField(JWT_TOKEN, openMetadataJWTClientConfig.getJwtToken(), authProvider);
openMetadataServerConnection.setSecurityConfig(openMetadataJWTClientConfig);

View File

@ -28,7 +28,8 @@
"upstream",
"appliedTo",
"relatedTo",
"reviews"
"reviews",
"reactedTo"
],
"javaEnums": [
{ "name": "CONTAINS" },

View File

@ -33,7 +33,8 @@ class EnumBackwardCompatibilityTest {
/** */
@Test
void testRelationshipEnumBackwardCompatible() {
assertEquals(17, Relationship.values().length);
assertEquals(18, Relationship.values().length);
assertEquals(17, Relationship.REACTED_TO.ordinal());
assertEquals(16, Relationship.REVIEWS.ordinal());
}

View File

@ -32,6 +32,7 @@ import static org.openmetadata.catalog.util.TestUtils.ADMIN_AUTH_HEADERS;
import static org.openmetadata.catalog.util.TestUtils.ADMIN_USER_NAME;
import static org.openmetadata.catalog.util.TestUtils.NON_EXISTENT_ENTITY;
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.assertListNotNull;
import static org.openmetadata.catalog.util.TestUtils.assertResponse;
import static org.openmetadata.catalog.util.TestUtils.assertResponseContains;
@ -425,10 +426,12 @@ public class FeedResourceTest extends CatalogApplicationTest {
String originalJson = JsonUtils.pojoToJson(thread);
// add reactions
Reaction reaction = new Reaction().withReactionType(ReactionType.HOORAY).withUser(USER.getEntityReference());
Reaction reaction = new Reaction().withReactionType(ReactionType.HOORAY).withUser(USER2.getEntityReference());
Thread updated = thread.withReactions(List.of(reaction));
patchThreadAndCheck(updated, originalJson, ADMIN_AUTH_HEADERS);
Thread patched = patchThreadAndCheck(updated, originalJson, TEST_AUTH_HEADERS);
assertNotEquals(patched.getUpdatedAt(), thread.getUpdatedAt());
assertEquals(TEST_USER_NAME, patched.getUpdatedBy());
}
@Test
@ -668,10 +671,13 @@ public class FeedResourceTest extends CatalogApplicationTest {
Post post = thread.getPosts().get(0);
String originalJson = JsonUtils.pojoToJson(post);
Reaction reaction1 = new Reaction().withReactionType(ReactionType.ROCKET).withUser(USER2.getEntityReference());
Reaction reaction2 = new Reaction().withReactionType(ReactionType.HOORAY).withUser(USER.getEntityReference());
Reaction reaction2 = new Reaction().withReactionType(ReactionType.HOORAY).withUser(USER2.getEntityReference());
post.withReactions(List.of(reaction1, reaction2));
Post updatedPost = patchPostAndCheck(thread.getId(), post, originalJson, AUTH_HEADERS);
Post updatedPost = patchPostAndCheck(thread.getId(), post, originalJson, TEST_AUTH_HEADERS);
assertTrue(containsAll(updatedPost.getReactions(), List.of(reaction1, reaction2), REACTION_COMPARATOR));
ThreadList threads = listThreads(null, 5, AUTH_HEADERS);
thread = threads.getData().get(0);
assertEquals(TEST_USER_NAME, thread.getUpdatedBy());
}
@Test

View File

@ -172,7 +172,7 @@ airflowConfiguration:
username: ${AIRFLOW_USERNAME:-admin}
password: ${AIRFLOW_PASSWORD:-admin}
metadataApiEndpoint: ${SERVER_HOST_API_URL:-http://localhost:8585/api}
authProvider: ${AIRFLOW_AUTH_PROVIDER:-"no-auth"} # Possible values are "no-auth", "azure", "google", "okta", "auth0", "customOidc"
authProvider: ${AIRFLOW_AUTH_PROVIDER:-"no-auth"} # Possible values are "no-auth", "azure", "google", "okta", "auth0", "customOidc", "openmetadata"
authConfig:
azure:
clientSecret: ${OM_AUTH_AIRFLOW_AZURE_CLIENT_SECRET:-""}
@ -196,7 +196,7 @@ airflowConfiguration:
clientId: ${OM_AUTH_AIRFLOW_CUSTOM_OIDC_CLIENT_ID:-""}
secretKey: ${OM_AUTH_AIRFLOW_CUSTOM_OIDC_SECRET_KEY_PATH:-""}
tokenEndpoint: ${OM_AUTH_AIRFLOW_CUSTOM_OIDC_TOKEN_ENDPOINT_URL:-""}
openMetadataJWT:
openmetadata:
jwtToken: ${OM_AUTH_JWT_TOKEN:-""}
slackEventPublishers:

View File

@ -28,7 +28,8 @@
"upstream",
"appliedTo",
"relatedTo",
"reviews"
"reviews",
"reactedTo"
],
"javaEnums": [
{ "name": "CONTAINS" },