fix: group history endpoint, user-only group list, reset-password, change-password path
- im-service: add GET /messages/group-history/{groupId} for group message history
- im-service: add findGroupHistory query to ImMessageRepository
- im-service: listGroups now filters by user membership (JSON_CONTAINS on member_ids)
- im-service: add groupHistory/listUserGroups/addGroupMember/removeGroupMember methods
- demo-service: add POST /auth/reset-password (unauthenticated forgot-password flow)
- demo-service: rename /user/reset-password → /user/change-password to match client
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
这个提交包含在:
父节点
8011fe591a
当前提交
624554a173
@ -60,6 +60,22 @@ public class DemoAuthController {
|
||||
);
|
||||
}
|
||||
|
||||
@PostMapping("/reset-password")
|
||||
public ApiResponse<Void> resetPassword(@RequestBody ResetPasswordRequest body) {
|
||||
if (body.appId() == null || body.appId().isBlank()) {
|
||||
return ApiResponse.badRequest("appId is required");
|
||||
}
|
||||
if (body.userId() == null || body.userId().isBlank()) {
|
||||
return ApiResponse.badRequest("userId is required");
|
||||
}
|
||||
if (body.newPassword() == null || body.newPassword().length() < 6) {
|
||||
return ApiResponse.badRequest("password must be at least 6 characters");
|
||||
}
|
||||
authService.resetPassword(body.appId(), body.userId(), body.newPassword());
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
public record RegisterRequest(String appId, String userId, String password, String nickname) {}
|
||||
public record LoginRequest(String appId, String userId, String password) {}
|
||||
public record ResetPasswordRequest(String appId, String userId, String newPassword) {}
|
||||
}
|
||||
|
||||
@ -36,8 +36,8 @@ public class DemoUserController {
|
||||
userService.updateProfile(appId, userId, body.nickname(), body.avatar(), body.gender()));
|
||||
}
|
||||
|
||||
@PostMapping("/user/reset-password")
|
||||
public ApiResponse<Void> resetPassword(
|
||||
@PostMapping("/user/change-password")
|
||||
public ApiResponse<Void> changePassword(
|
||||
@RequestParam String appId,
|
||||
Authentication auth,
|
||||
@RequestBody ResetPasswordRequest body) {
|
||||
|
||||
@ -83,6 +83,14 @@ public class DemoAuthService {
|
||||
return new AuthResult(demoToken, imToken, toProfile(user));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void resetPassword(String appId, String userId, String newPassword) {
|
||||
DemoUserEntity user = userRepository.findByAppIdAndUserId(appId, userId)
|
||||
.orElseThrow(() -> new BusinessException(404, "User not found: " + userId));
|
||||
user.setPasswordHash(passwordEncoder.encode(newPassword));
|
||||
userRepository.save(user);
|
||||
}
|
||||
|
||||
private String generateDemoToken(String appId, String userId) {
|
||||
return jwtUtil.generate(userId, Map.of("appId", appId, "role", "USER"));
|
||||
}
|
||||
|
||||
@ -30,8 +30,9 @@ public class GroupController {
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<ApiResponse<List<ImGroupEntity>>> list(
|
||||
@RequestParam String appId) {
|
||||
return ResponseEntity.ok(ApiResponse.success(groupService.listByApp(appId)));
|
||||
@RequestParam String appId,
|
||||
@AuthenticationPrincipal String userId) {
|
||||
return ResponseEntity.ok(ApiResponse.success(groupService.listUserGroups(appId, userId)));
|
||||
}
|
||||
|
||||
@PostMapping("/{groupId}/members")
|
||||
|
||||
@ -51,4 +51,14 @@ public class MessageController {
|
||||
@RequestParam(defaultValue = "20") int size) {
|
||||
return ResponseEntity.ok(ApiResponse.success(messageService.history(appId, userId, toId, page, size)));
|
||||
}
|
||||
|
||||
@GetMapping("/group-history/{groupId}")
|
||||
public ResponseEntity<ApiResponse<?>> groupHistory(
|
||||
@PathVariable String groupId,
|
||||
@AuthenticationPrincipal String userId,
|
||||
@RequestParam String appId,
|
||||
@RequestParam(defaultValue = "0") int page,
|
||||
@RequestParam(defaultValue = "20") int size) {
|
||||
return ResponseEntity.ok(ApiResponse.success(messageService.groupHistory(appId, groupId, page, size)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,9 +2,21 @@ package com.xuqm.im.repository;
|
||||
|
||||
import com.xuqm.im.entity.ImGroupEntity;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import java.util.List;
|
||||
|
||||
public interface ImGroupRepository extends JpaRepository<ImGroupEntity, String> {
|
||||
List<ImGroupEntity> findByAppId(String appId);
|
||||
long countByAppId(String appId);
|
||||
|
||||
@Query(value = """
|
||||
SELECT * FROM im_group
|
||||
WHERE app_id = :appId
|
||||
AND JSON_CONTAINS(member_ids, JSON_QUOTE(:userId))
|
||||
ORDER BY created_at DESC
|
||||
""", nativeQuery = true)
|
||||
List<ImGroupEntity> findUserGroups(
|
||||
@Param("appId") String appId,
|
||||
@Param("userId") String userId);
|
||||
}
|
||||
|
||||
@ -64,6 +64,18 @@ public interface ImMessageRepository extends JpaRepository<ImMessageEntity, Stri
|
||||
@Param("peerId") String peerId,
|
||||
Pageable pageable);
|
||||
|
||||
@Query("""
|
||||
select m from ImMessageEntity m
|
||||
where m.appId = :appId
|
||||
and m.chatType = com.xuqm.im.entity.ImMessageEntity$ChatType.GROUP
|
||||
and m.toId = :groupId
|
||||
order by m.createdAt desc
|
||||
""")
|
||||
Page<ImMessageEntity> findGroupHistory(
|
||||
@Param("appId") String appId,
|
||||
@Param("groupId") String groupId,
|
||||
Pageable pageable);
|
||||
|
||||
long countByAppId(String appId);
|
||||
|
||||
@Query("select count(m) from ImMessageEntity m where m.appId = :appId and m.createdAt >= :since")
|
||||
|
||||
@ -67,6 +67,10 @@ public class ImGroupService {
|
||||
return groupRepository.findByAppId(appId);
|
||||
}
|
||||
|
||||
public List<ImGroupEntity> listUserGroups(String appId, String userId) {
|
||||
return groupRepository.findUserGroups(appId, userId);
|
||||
}
|
||||
|
||||
private String toJson(List<String> list) {
|
||||
try { return objectMapper.writeValueAsString(list); } catch (Exception e) { return "[]"; }
|
||||
}
|
||||
|
||||
@ -109,6 +109,10 @@ public class MessageService {
|
||||
appId, userId, toId, PageRequest.of(page, size));
|
||||
}
|
||||
|
||||
public Page<ImMessageEntity> groupHistory(String appId, String groupId, int page, int size) {
|
||||
return messageRepository.findGroupHistory(appId, groupId, PageRequest.of(page, size));
|
||||
}
|
||||
|
||||
public List<ImMessageRepository.ConversationSummary> conversations(String appId, String userId, int size) {
|
||||
return messageRepository.findConversations(appId, userId, size);
|
||||
}
|
||||
|
||||
正在加载...
在新工单中引用
屏蔽一个用户