From c9b356b46a44ad80209c707549294f76ef916c8f Mon Sep 17 00:00:00 2001 From: TowyTowy <85077986+TowyTowy@users.noreply.github.com> Date: Sun, 12 Jul 2026 11:23:58 +0200 Subject: [PATCH] fix(memo): populate parent relation in comment webhook payload (#6083) Co-authored-by: Claude Fable 5 --- .../api/v1/memo_comment_relations_test.go | 47 +++++++++++++++++++ server/router/api/v1/memo_service.go | 11 +++++ 2 files changed, 58 insertions(+) create mode 100644 server/router/api/v1/memo_comment_relations_test.go diff --git a/server/router/api/v1/memo_comment_relations_test.go b/server/router/api/v1/memo_comment_relations_test.go new file mode 100644 index 00000000..c1571cad --- /dev/null +++ b/server/router/api/v1/memo_comment_relations_test.go @@ -0,0 +1,47 @@ +package v1 + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + v1pb "github.com/usememos/memos/proto/gen/api/v1" + "github.com/usememos/memos/store" +) + +// TestCreateMemoComment_ReturnsParentRelation verifies that the memo returned by +// CreateMemoComment carries the COMMENT relation to its parent memo. The comment +// memo is converted before the relation is created, so without an explicit reload +// the returned memo (and the memo.comment.created webhook payload built from it) +// would have an empty Relations slice. Regression test for usememos/memos#6081. +func TestCreateMemoComment_ReturnsParentRelation(t *testing.T) { + ctx := context.Background() + svc := newIntegrationService(t) + + author, err := svc.Store.CreateUser(ctx, &store.User{ + Username: "author", Role: store.RoleAdmin, Email: "author@example.com", + }) + require.NoError(t, err) + authorCtx := userCtx(ctx, author.ID) + + parent, err := svc.CreateMemo(authorCtx, &v1pb.CreateMemoRequest{ + Memo: &v1pb.Memo{Content: "parent memo", Visibility: v1pb.Visibility_PUBLIC}, + }) + require.NoError(t, err) + + comment, err := svc.CreateMemoComment(authorCtx, &v1pb.CreateMemoCommentRequest{ + Name: parent.Name, + Comment: &v1pb.Memo{Content: "a comment", Visibility: v1pb.Visibility_PUBLIC}, + }) + require.NoError(t, err) + + require.Len(t, comment.Relations, 1, "comment memo should carry its parent relation") + rel := comment.Relations[0] + assert.Equal(t, v1pb.MemoRelation_COMMENT, rel.Type) + require.NotNil(t, rel.Memo) + require.NotNil(t, rel.RelatedMemo) + assert.Equal(t, comment.Name, rel.Memo.Name) + assert.Equal(t, parent.Name, rel.RelatedMemo.Name) +} diff --git a/server/router/api/v1/memo_service.go b/server/router/api/v1/memo_service.go index 21afdf37..5c18e38b 100644 --- a/server/router/api/v1/memo_service.go +++ b/server/router/api/v1/memo_service.go @@ -701,6 +701,17 @@ func (s *APIV1Service) CreateMemoComment(ctx context.Context, request *v1pb.Crea if err != nil { return nil, status.Errorf(codes.Internal, "failed to create memo relation") } + + // The comment memo was converted before the relation above existed, so its + // Relations slice is empty. Reload the relations now so that both the API + // response and the memo.comment.created webhook payload carry the relation + // to the parent memo. + relations, err := s.loadMemoRelations(ctx, memo) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to load memo relations") + } + memoComment.Relations = relations + creator, err := ResolveUserByName(ctx, s.Store, memoComment.Creator) if err != nil { return nil, status.Errorf(codes.InvalidArgument, "invalid memo creator")