feat(chat): add endpoint to get quoted message by ID
All checks were successful
Build Backend / build (push) Successful in 2m21s
Build Backend / build-docker (push) Successful in 58s

Add GET /api/v1/messages/:id endpoint to retrieve quoted/replied messages
for preview fill and navigation purposes. The endpoint includes authorization
checks ensuring only conversation participants can access the message.

Additionally improve file upload handling for native clients (expo-file-system)
by accepting explicit displayName from frontend, with sanitization to prevent
path traversal and 255-character length limit. File extension detection now
prioritizes the real display name over the multipart header filename.
This commit is contained in:
lafay
2026-07-02 23:22:24 +08:00
parent d8e56e60dc
commit d240485d0e
5 changed files with 109 additions and 7 deletions

View File

@@ -55,6 +55,8 @@ type ChatService interface {
// 消息扩展功能
RecallMessage(ctx context.Context, messageID string, userID string) error
DeleteMessage(ctx context.Context, messageID string, userID string) error
// GetReplyMessage 按 ID 获取被引用消息(鉴权:必须是该会话参与者)
GetReplyMessage(ctx context.Context, messageID string, userID string) (*model.Message, error)
// 实时事件相关
SendTyping(ctx context.Context, senderID string, conversationID string)
@@ -987,6 +989,23 @@ func (s *chatServiceImpl) DeleteMessage(ctx context.Context, messageID string, u
return nil
}
// GetReplyMessage 按消息 ID 获取被引用消息(用于引用预览/跳转的回填)
// 鉴权:调用者必须是该消息所属会话的参与者,否则拒绝(防止 IDOR
func (s *chatServiceImpl) GetReplyMessage(ctx context.Context, messageID string, userID string) (*model.Message, error) {
message, err := s.repo.GetMessageByID(messageID)
if err != nil {
return nil, errors.New("message not found")
}
// 验证用户是否是会话参与者
_, err = s.getParticipant(ctx, message.ConversationID, userID)
if err != nil {
return nil, errors.New("no permission to view this message")
}
return message, nil
}
// SendTyping 发送正在输入状态
func (s *chatServiceImpl) SendTyping(ctx context.Context, senderID string, conversationID string) {
if s.wsHub == nil {