package com.xuqm.push.controller; import com.xuqm.common.model.ApiResponse; import com.xuqm.push.entity.DeviceLoginLogEntity; import com.xuqm.push.entity.DeviceTokenEntity; import com.xuqm.push.entity.PushUserEntity; import com.xuqm.push.repository.DeviceTokenRepository; import com.xuqm.push.service.PushAccountService; import com.xuqm.push.service.PushDiagnosticsService; import com.xuqm.push.service.PushOperationLogService; import java.util.LinkedHashMap; import org.springframework.data.domain.Page; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; import java.util.Map; @RestController @RequestMapping("/api/push/admin") @PreAuthorize("hasAnyAuthority('ROLE_OPS', 'ROLE_TENANT', 'ROLE_ADMIN')") public class PushManagementController { private final PushDiagnosticsService diagnosticsService; private final PushAccountService accountService; private final PushOperationLogService opLogService; private final DeviceTokenRepository tokenRepository; public PushManagementController(PushDiagnosticsService diagnosticsService, PushAccountService accountService, PushOperationLogService opLogService, DeviceTokenRepository tokenRepository) { this.diagnosticsService = diagnosticsService; this.accountService = accountService; this.opLogService = opLogService; this.tokenRepository = tokenRepository; } // ---- user account management ---- @GetMapping("/users") public ResponseEntity>> listUsers( @RequestParam String appKey, @RequestParam(required = false, defaultValue = "") String keyword, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "20") int size) { Page result = accountService.listUsers(appKey, keyword, page, size); return ResponseEntity.ok(ApiResponse.success(Map.of( "content", result.getContent(), "total", result.getTotalElements(), "totalPages", result.getTotalPages() ))); } @GetMapping("/users/{userId}") public ResponseEntity> getUser( @PathVariable String userId, @RequestParam String appKey) { return ResponseEntity.ok(ApiResponse.success(accountService.getAccount(appKey, userId))); } @PutMapping("/users/{userId}") public ResponseEntity> updateUser( @PathVariable String userId, @RequestBody UpdateUserRequest request) { PushUserEntity.Gender gender = null; if (request.gender() != null && !request.gender().isBlank()) { try { gender = PushUserEntity.Gender.valueOf(request.gender().toUpperCase()); } catch (Exception ignored) {} } PushUserEntity updated = accountService.updateAccount(request.appKey(), userId, request.nickname(), request.avatar(), gender); opLogService.record(request.appKey(), "UPDATE_USER", "ACCOUNT", userId, "编辑用户 " + userId + " 的信息", null); return ResponseEntity.ok(ApiResponse.success(updated)); } @PutMapping("/users/{userId}/status") public ResponseEntity> setUserStatus( @PathVariable String userId, @RequestBody UserStatusRequest request) { PushUserEntity.Status status; try { status = PushUserEntity.Status.valueOf(request.status().toUpperCase()); } catch (Exception e) { return ResponseEntity.badRequest().body(ApiResponse.error(400, "无效的状态值,可选:ACTIVE, BANNED")); } PushUserEntity result = accountService.setUserStatus(request.appKey(), userId, status); String statusLabel = status == PushUserEntity.Status.BANNED ? "禁用" : "启用"; opLogService.record(request.appKey(), "UPDATE_USER_STATUS", "ACCOUNT", userId, statusLabel + "用户 " + userId, null); return ResponseEntity.ok(ApiResponse.success(result)); } @DeleteMapping("/users/{userId}") public ResponseEntity> deleteUser( @PathVariable String userId, @RequestParam String appKey) { accountService.deleteAccount(appKey, userId); opLogService.record(appKey, "DELETE_USER", "ACCOUNT", userId, "删除用户 " + userId, null); return ResponseEntity.ok(ApiResponse.ok()); } @PostMapping("/users/import") public ResponseEntity> importUser(@RequestBody ImportUserRequest request) { PushUserEntity.Gender gender = null; if (request.gender() != null && !request.gender().isBlank()) { try { gender = PushUserEntity.Gender.valueOf(request.gender().toUpperCase()); } catch (Exception ignored) {} } PushUserEntity.Status status = null; if (request.status() != null && !request.status().isBlank()) { try { status = PushUserEntity.Status.valueOf(request.status().toUpperCase()); } catch (Exception ignored) {} } PushUserEntity user = accountService.importAccount(request.appKey(), request.userId(), request.nickname(), request.avatar(), gender, status); opLogService.record(request.appKey(), "IMPORT_USER", "ACCOUNT", request.userId(), "导入用户 " + request.userId(), null); return ResponseEntity.ok(ApiResponse.success(user)); } // ---- diagnostics ---- @GetMapping("/user-status") public ResponseEntity> userStatus( @RequestParam String appKey, @RequestParam String userId) { return ResponseEntity.ok(ApiResponse.success(diagnosticsService.searchByUserId(appKey, userId))); } @GetMapping("/device-logs") public ResponseEntity>> deviceLogs( @RequestParam String appKey, @RequestParam String userId, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "20") int size) { Page result = diagnosticsService.deviceLogs(appKey, userId, page, size); return ResponseEntity.ok(ApiResponse.success(Map.of( "content", result.getContent(), "total", result.getTotalElements(), "totalPages", result.getTotalPages() ))); } @PostMapping("/test-offline") public ResponseEntity> testOffline( @RequestBody TestOfflineRequest request) { PushDiagnosticsService.TestPushResult result = diagnosticsService.sendTestOfflineMessage( request.appKey(), request.userId(), request.title(), request.body(), request.payload()); opLogService.record(request.appKey(), "TEST_PUSH", "PUSH", request.userId(), "向 " + request.userId() + " 发送测试推送", null); return ResponseEntity.ok(ApiResponse.success(result)); } @GetMapping("/devices/{id}/token") public ResponseEntity>> getDeviceToken( @PathVariable String id, @RequestParam String appKey) { return tokenRepository.findById(id) .filter(e -> appKey.equals(e.getAppKey())) .map(e -> ResponseEntity.ok(ApiResponse.success(Map.of("token", e.getToken())))) .orElseGet(() -> ResponseEntity.ok(ApiResponse.error(404, "设备不存在"))); } public record UpdateUserRequest(String appKey, String nickname, String avatar, String gender) {} public record UserStatusRequest(String appKey, String status) {} public record ImportUserRequest(String appKey, String userId, String nickname, String avatar, String gender, String status) {} public record TestOfflineRequest(String appKey, String userId, String title, String body, String payload) {} }