package com.xuqm.tenant.controller; import com.xuqm.common.model.ApiResponse; import com.xuqm.tenant.dto.LoginRequest; import com.xuqm.tenant.dto.RegisterRequest; import com.xuqm.tenant.service.AuthService; import com.xuqm.tenant.service.EmailService; import jakarta.validation.Valid; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; 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.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.security.SecureRandom; import java.util.Base64; import java.util.Map; import java.util.UUID; import javax.imageio.ImageIO; @RestController @RequestMapping("/api/auth") public class AuthController { private final AuthService authService; private final EmailService emailService; private static final SecureRandom random = new SecureRandom(); private static final String CHARS = "23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz"; public AuthController(AuthService authService, EmailService emailService) { this.authService = authService; this.emailService = emailService; } @GetMapping("/captcha") public ResponseEntity>> captcha() throws Exception { String key = UUID.randomUUID().toString(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < 4; i++) { sb.append(CHARS.charAt(random.nextInt(CHARS.length()))); } String code = sb.toString(); authService.storeCaptcha(key, code); BufferedImage img = new BufferedImage(120, 40, BufferedImage.TYPE_INT_RGB); Graphics2D g = img.createGraphics(); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setColor(new Color(245, 245, 245)); g.fillRect(0, 0, 120, 40); g.setFont(new Font("Arial", Font.BOLD, 24)); for (int i = 0; i < code.length(); i++) { g.setColor(new Color(random.nextInt(150), random.nextInt(150), random.nextInt(150))); g.drawString(String.valueOf(code.charAt(i)), 10 + i * 28, 30); } for (int i = 0; i < 5; i++) { g.setColor(new Color(random.nextInt(200), random.nextInt(200), random.nextInt(200))); g.drawLine(random.nextInt(120), random.nextInt(40), random.nextInt(120), random.nextInt(40)); } g.dispose(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(img, "png", baos); String base64 = Base64.getEncoder().encodeToString(baos.toByteArray()); return ResponseEntity.ok(ApiResponse.success(Map.of( "key", key, "image", "data:image/png;base64," + base64 ))); } @PostMapping("/send-email-code") public ResponseEntity> sendEmailCode(@RequestParam @NotBlank @Email String email, @RequestParam @NotBlank String purpose) { emailService.sendVerificationCode(email, purpose); return ResponseEntity.ok(ApiResponse.ok()); } @PostMapping("/register") public ResponseEntity> register(@Valid @RequestBody RegisterRequest req) { authService.register(req); return ResponseEntity.ok(ApiResponse.ok()); } @PostMapping("/login") public ResponseEntity>> login(@Valid @RequestBody LoginRequest req) { String token = authService.login(req); return ResponseEntity.ok(ApiResponse.success(Map.of("token", token))); } @PostMapping("/forgot-password") public ResponseEntity> forgotPassword(@RequestParam @NotBlank @Email String email) { authService.forgotPassword(email); return ResponseEntity.ok(ApiResponse.ok()); } @PostMapping("/reset-password") public ResponseEntity> resetPassword( @RequestParam @NotBlank @Email String email, @RequestParam @NotBlank String code, @RequestParam @NotBlank String newPassword) { authService.resetPassword(email, code, newPassword); return ResponseEntity.ok(ApiResponse.ok()); } }