Merge branch 'wyh'

Change-Id: I9b3ccf2404566516f12dea946873bc3b0d2b92e9
diff --git a/pom.xml b/pom.xml
index f1932cb..9238ad6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -92,6 +92,14 @@
             <artifactId>junit</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-mail</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/src/main/java/com/example/g8backend/config/RedisConfig.java b/src/main/java/com/example/g8backend/config/RedisConfig.java
new file mode 100644
index 0000000..023772a
--- /dev/null
+++ b/src/main/java/com/example/g8backend/config/RedisConfig.java
@@ -0,0 +1,21 @@
+package com.example.g8backend.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+@Configuration
+public class RedisConfig {
+
+    @Bean
+    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Object> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+        template.setKeySerializer(new StringRedisSerializer());
+        template.setValueSerializer(new StringRedisSerializer());
+        return template;
+    }
+}
diff --git a/src/main/java/com/example/g8backend/controller/AuthController.java b/src/main/java/com/example/g8backend/controller/AuthController.java
index 11446f9..39183c1 100644
--- a/src/main/java/com/example/g8backend/controller/AuthController.java
+++ b/src/main/java/com/example/g8backend/controller/AuthController.java
@@ -1,15 +1,19 @@
 package com.example.g8backend.controller;
 
+import com.example.g8backend.dto.UserRegisterDTO;
 import com.example.g8backend.entity.User;
 import com.example.g8backend.service.IUserService;
 import com.example.g8backend.util.JwtUtil;
+import com.example.g8backend.util.mailUtil;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.http.ResponseEntity;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.UUID;
 
 @RestController
 @RequestMapping("/auth")
@@ -19,18 +23,52 @@
     private IUserService userService;
 
     @Autowired
+    private mailUtil mailUtil;
+
+    @Autowired
     private PasswordEncoder passwordEncoder;
 
     @Autowired
     private JwtUtil jwtUtil;
 
+    @Autowired
+    RedisTemplate<String, Object> redisTemplate;
+
+    // 发送验证码
+    @PostMapping("/send_verification_code")
+    public ResponseEntity<?> sendVerificationCode(@RequestBody UserRegisterDTO registerDTO) {
+        if (userService.getUserByEmail(registerDTO.getEmail()) != null) {
+            return ResponseEntity.badRequest().body("邮箱已存在");
+        }
+
+        String verificationCode = UUID.randomUUID().toString().substring(0, 6);
+        mailUtil.sendMail(registerDTO.getEmail(), "PT平台注册验证码", "您的验证码为:" + verificationCode + ",验证码十分钟内有效,请勿泄露。");
+
+        redisTemplate.opsForValue().set(registerDTO.getEmail(), verificationCode, 10 * 60, java.util.concurrent.TimeUnit.SECONDS);
+        return ResponseEntity.ok("验证码发送成功");
+    }
+
     // 用户注册
     @PostMapping("/register")
-    public ResponseEntity<?> register(@RequestBody User user) {
-        if (userService.getUserByName(user.getUserName()) != null) {
+    public ResponseEntity<?> register(@RequestBody UserRegisterDTO registerDTO) {
+        if (userService.getUserByName(registerDTO.getUserName()) != null) {
             return ResponseEntity.badRequest().body("用户名已存在");
         }
+
+        if (!redisTemplate.hasKey(registerDTO.getInvitationCode())) {
+            return ResponseEntity.badRequest().body("邀请码错误");
+        }
+        if (!registerDTO.getVerificationCode().equals(redisTemplate.opsForValue().get(registerDTO.getEmail()))) {
+            return ResponseEntity.badRequest().body("验证码错误");
+        }
+        redisTemplate.delete(registerDTO.getEmail());
+
+        User user = new User();
+        user.setUserName(registerDTO.getUserName());
+        user.setPassword(passwordEncoder.encode(registerDTO.getPassword()));
+        user.setEmail(registerDTO.getEmail());
         userService.registerUser(user);
+
         return ResponseEntity.ok("注册成功");
     }
 
@@ -46,4 +84,10 @@
         response.put("token", token);
         return ResponseEntity.ok(response);
     }
+
+    @GetMapping("/test_redis")
+    public ResponseEntity<?> testRedis() {
+        redisTemplate.opsForValue().get("test");
+        return ResponseEntity.ok("test redis ok");
+    }
 }
\ No newline at end of file
diff --git a/src/main/java/com/example/g8backend/dto/UserRegisterDTO.java b/src/main/java/com/example/g8backend/dto/UserRegisterDTO.java
new file mode 100644
index 0000000..2214438
--- /dev/null
+++ b/src/main/java/com/example/g8backend/dto/UserRegisterDTO.java
@@ -0,0 +1,12 @@
+package com.example.g8backend.dto;
+
+import lombok.Data;
+
+@Data
+public class UserRegisterDTO {
+    private String userName;
+    private String password;
+    private String email;
+    private String verificationCode;
+    private String invitationCode;
+}
diff --git a/src/main/java/com/example/g8backend/service/UserServiceImpl.java b/src/main/java/com/example/g8backend/service/UserServiceImpl.java
index a382a89..567c5f3 100644
--- a/src/main/java/com/example/g8backend/service/UserServiceImpl.java
+++ b/src/main/java/com/example/g8backend/service/UserServiceImpl.java
@@ -24,11 +24,5 @@
     public User getUserByEmail(String email) { return userMapper.getUserByEmail(email);}
 
     @Override
-    public void registerUser(User user) {
-        String password = user.getPassword(); // 获取密码
-        String encodedPassword = passwordEncoder.encode(password); // 加密密码
-        user.setPassword(encodedPassword);
-        System.out.println(user.getPassword());
-        userMapper.insert(user); // 调用 UserMapper 的 insert 方法
-    }
+    public void registerUser(User user) {userMapper.insert(user);}
 }
diff --git a/src/main/java/com/example/g8backend/util/mailUtil.java b/src/main/java/com/example/g8backend/util/mailUtil.java
new file mode 100644
index 0000000..5c8ad55
--- /dev/null
+++ b/src/main/java/com/example/g8backend/util/mailUtil.java
@@ -0,0 +1,24 @@
+package com.example.g8backend.util;
+
+import org.springframework.mail.SimpleMailMessage;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.stereotype.Component;
+
+@Component
+public class mailUtil {
+
+    private final JavaMailSender javaMailSender;
+
+    public mailUtil(JavaMailSender javaMailSender) {
+        this.javaMailSender = javaMailSender;
+    }
+
+    public void sendMail(String to, String subject, String message) {
+        SimpleMailMessage mail = new SimpleMailMessage();
+        mail.setFrom("2038234690@qq.com");
+        mail.setTo(to);
+        mail.setSubject(subject);
+        mail.setText(message);
+        javaMailSender.send(mail);
+    }
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 6e7d6ce..7f85f87 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -5,3 +5,16 @@
 spring.sql.init.mode=always
 
 mybatis-plus.mapper-locations=classpath*:/mapper/**/*.xml
+
+spring.data.redis.host = 127.0.0.1
+spring.data.redis.port = 6379
+
+spring.mail.host=smtp.qq.com
+spring.mail.port=465
+spring.mail.username=2038234690@qq.com
+spring.mail.password=dixhyfaxjyauehaa
+spring.mail.default-encoding=utf-8
+spring.mail.protocol=smtp
+spring.mail.properties.mail.smtp.auth=true
+spring.mail.properties.mail.smtp.ssl.enable=true
+spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
diff --git a/src/test/java/com/example/g8backend/util/JwtUtilTest.java b/src/test/java/com/example/g8backend/util/JwtUtilTest.java
new file mode 100644
index 0000000..860acec
--- /dev/null
+++ b/src/test/java/com/example/g8backend/util/JwtUtilTest.java
@@ -0,0 +1,49 @@
+package com.example.g8backend.util;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.MockitoAnnotations;
+import static org.junit.jupiter.api.Assertions.*;
+import io.jsonwebtoken.security.Keys;
+import javax.crypto.SecretKey;
+import java.security.SecureRandom;
+
+class JwtUtilTest {
+
+    @InjectMocks
+    private JwtUtil jwtUtil;
+
+    @BeforeEach
+    void setUp() {
+        MockitoAnnotations.openMocks(this);
+        byte[] keyBytes = new byte[32];
+        new SecureRandom().nextBytes(keyBytes);
+        SecretKey secretKey = Keys.hmacShaKeyFor(keyBytes);
+        jwtUtil = new JwtUtil(secretKey);
+    }
+
+    @Test
+    void testGenerateToken() {
+        String username = "testUser";
+        String token = jwtUtil.generateToken(username);
+        assertNotNull(token);
+    }
+
+    @Test
+    void testValidateTokenAndGetUsername() {
+        String username = "testUser";
+        String token = jwtUtil.generateToken(username);
+        String extractedUsername = jwtUtil.validateTokenAndGetUsername(token);
+        assertEquals(username, extractedUsername);
+    }
+
+    @Test
+    void testValidateTokenAndGetUsername_InvalidToken() {
+        String invalidToken = "invalid.token.here";
+        Exception exception = assertThrows(RuntimeException.class, () ->
+                jwtUtil.validateTokenAndGetUsername(invalidToken)
+        );
+        assertTrue(exception.getMessage().contains("Token无效或过期"));
+    }
+}