Commit b2b67f4754e38687422da44c564ff0372aac0682
1 parent
3be59f71
feat(usr): jjwt deps + login DTO/VO + error codes REQ-USR-004
Showing
6 changed files
with
129 additions
and
0 deletions
backend/pom.xml
| ... | ... | @@ -82,6 +82,25 @@ |
| 82 | 82 | <version>${hutool.version}</version> |
| 83 | 83 | </dependency> |
| 84 | 84 | |
| 85 | + <!-- REQ-USR-004 JWT (jjwt 0.12.x) --> | |
| 86 | + <dependency> | |
| 87 | + <groupId>io.jsonwebtoken</groupId> | |
| 88 | + <artifactId>jjwt-api</artifactId> | |
| 89 | + <version>0.12.6</version> | |
| 90 | + </dependency> | |
| 91 | + <dependency> | |
| 92 | + <groupId>io.jsonwebtoken</groupId> | |
| 93 | + <artifactId>jjwt-impl</artifactId> | |
| 94 | + <version>0.12.6</version> | |
| 95 | + <scope>runtime</scope> | |
| 96 | + </dependency> | |
| 97 | + <dependency> | |
| 98 | + <groupId>io.jsonwebtoken</groupId> | |
| 99 | + <artifactId>jjwt-jackson</artifactId> | |
| 100 | + <version>0.12.6</version> | |
| 101 | + <scope>runtime</scope> | |
| 102 | + </dependency> | |
| 103 | + | |
| 85 | 104 | <dependency> |
| 86 | 105 | <groupId>org.springframework.boot</groupId> |
| 87 | 106 | <artifactId>spring-boot-starter-test</artifactId> | ... | ... |
backend/src/main/java/com/xly/erp/common/response/ErrorCode.java
| ... | ... | @@ -6,6 +6,8 @@ import lombok.Getter; |
| 6 | 6 | public enum ErrorCode { |
| 7 | 7 | SUCCESS(200, "操作成功"), |
| 8 | 8 | PARAM_INVALID(40010, "参数错误"), |
| 9 | + LOGIN_INVALID_CREDENTIALS(40101, "用户名或密码错误"), | |
| 10 | + LOGIN_ACCOUNT_LOCKED(40301, "账号已临时锁定"), | |
| 9 | 11 | MOD_PARENT_NOT_FOUND(40411, "父模块不存在或已删除"), |
| 10 | 12 | MOD_NOT_FOUND(40421, "模块不存在或已删除"), |
| 11 | 13 | STAFF_NOT_FOUND(40421, "职员不存在或已删除"), | ... | ... |
backend/src/main/java/com/xly/erp/module/usr/dto/LoginDTO.java
0 → 100644
| 1 | +package com.xly.erp.module.usr.dto; | |
| 2 | + | |
| 3 | +import jakarta.validation.constraints.NotBlank; | |
| 4 | +import jakarta.validation.constraints.Pattern; | |
| 5 | +import jakarta.validation.constraints.Size; | |
| 6 | +import lombok.Data; | |
| 7 | + | |
| 8 | +/** REQ-USR-004 用户登录入参 */ | |
| 9 | +@Data | |
| 10 | +public class LoginDTO { | |
| 11 | + | |
| 12 | + @NotBlank | |
| 13 | + @Size(max = 50) | |
| 14 | + private String sUserName; | |
| 15 | + | |
| 16 | + @NotBlank | |
| 17 | + @Size(max = 100) | |
| 18 | + private String sPassword; | |
| 19 | + | |
| 20 | + @NotBlank | |
| 21 | + @Pattern(regexp = "^standard$", message = "sVersion 仅支持 standard") | |
| 22 | + private String sVersion; | |
| 23 | +} | ... | ... |
backend/src/main/java/com/xly/erp/module/usr/vo/LoginResultVO.java
0 → 100644
| 1 | +package com.xly.erp.module.usr.vo; | |
| 2 | + | |
| 3 | +import lombok.AllArgsConstructor; | |
| 4 | +import lombok.Data; | |
| 5 | +import lombok.NoArgsConstructor; | |
| 6 | + | |
| 7 | +/** REQ-USR-004 登录结果 VO(含 JWT + 用户基本信息) */ | |
| 8 | +@Data | |
| 9 | +@NoArgsConstructor | |
| 10 | +@AllArgsConstructor | |
| 11 | +public class LoginResultVO { | |
| 12 | + private String accessToken; | |
| 13 | + private long expiresIn; | |
| 14 | + private LoginUserInfo user; | |
| 15 | + | |
| 16 | + @Data | |
| 17 | + @NoArgsConstructor | |
| 18 | + @AllArgsConstructor | |
| 19 | + public static class LoginUserInfo { | |
| 20 | + private Integer iIncrement; | |
| 21 | + private String sUserNo; | |
| 22 | + private String sUserName; | |
| 23 | + private String sUserType; | |
| 24 | + private String sLanguage; | |
| 25 | + } | |
| 26 | +} | ... | ... |
backend/src/test/java/com/xly/erp/common/response/ApiResponseTest.java
| ... | ... | @@ -55,5 +55,7 @@ class ApiResponseTest { |
| 55 | 55 | assertThat(ErrorCode.PERM_CATEGORY_NOT_FOUND.getCode()).isEqualTo(40422); |
| 56 | 56 | assertThat(ErrorCode.USR_USER_NAME_OR_NO_DUP.getCode()).isEqualTo(40921); |
| 57 | 57 | assertThat(ErrorCode.USR_NOT_FOUND.getCode()).isEqualTo(40431); |
| 58 | + assertThat(ErrorCode.LOGIN_INVALID_CREDENTIALS.getCode()).isEqualTo(40101); | |
| 59 | + assertThat(ErrorCode.LOGIN_ACCOUNT_LOCKED.getCode()).isEqualTo(40301); | |
| 58 | 60 | } |
| 59 | 61 | } | ... | ... |
backend/src/test/java/com/xly/erp/module/usr/dto/LoginDTOValidationTest.java
0 → 100644
| 1 | +package com.xly.erp.module.usr.dto; | |
| 2 | + | |
| 3 | +import jakarta.validation.ConstraintViolation; | |
| 4 | +import jakarta.validation.Validation; | |
| 5 | +import jakarta.validation.Validator; | |
| 6 | +import jakarta.validation.ValidatorFactory; | |
| 7 | +import org.junit.jupiter.api.Test; | |
| 8 | + | |
| 9 | +import java.util.Set; | |
| 10 | + | |
| 11 | +import static org.assertj.core.api.Assertions.assertThat; | |
| 12 | + | |
| 13 | +class LoginDTOValidationTest { | |
| 14 | + | |
| 15 | + private static final ValidatorFactory FACTORY = Validation.buildDefaultValidatorFactory(); | |
| 16 | + private final Validator validator = FACTORY.getValidator(); | |
| 17 | + | |
| 18 | + private LoginDTO valid() { | |
| 19 | + LoginDTO d = new LoginDTO(); | |
| 20 | + d.setSUserName("alice"); | |
| 21 | + d.setSPassword("666666"); | |
| 22 | + d.setSVersion("standard"); | |
| 23 | + return d; | |
| 24 | + } | |
| 25 | + | |
| 26 | + @Test | |
| 27 | + void allValid_yieldsNoViolations() { | |
| 28 | + Set<ConstraintViolation<LoginDTO>> v = validator.validate(valid()); | |
| 29 | + assertThat(v).isEmpty(); | |
| 30 | + } | |
| 31 | + | |
| 32 | + @Test | |
| 33 | + void blankRequiredFields_yieldsViolations() { | |
| 34 | + LoginDTO d = new LoginDTO(); | |
| 35 | + Set<ConstraintViolation<LoginDTO>> v = validator.validate(d); | |
| 36 | + assertThat(v).extracting(cv -> cv.getPropertyPath().toString()) | |
| 37 | + .contains("sUserName", "sPassword", "sVersion"); | |
| 38 | + } | |
| 39 | + | |
| 40 | + @Test | |
| 41 | + void invalidVersion_yieldsViolation() { | |
| 42 | + LoginDTO d = valid(); | |
| 43 | + d.setSVersion("experimental"); | |
| 44 | + Set<ConstraintViolation<LoginDTO>> v = validator.validate(d); | |
| 45 | + assertThat(v).extracting(cv -> cv.getPropertyPath().toString()).contains("sVersion"); | |
| 46 | + } | |
| 47 | + | |
| 48 | + @Test | |
| 49 | + void overSized_yieldsViolation() { | |
| 50 | + LoginDTO d = valid(); | |
| 51 | + d.setSUserName("a".repeat(51)); | |
| 52 | + d.setSPassword("p".repeat(101)); | |
| 53 | + Set<ConstraintViolation<LoginDTO>> v = validator.validate(d); | |
| 54 | + assertThat(v).extracting(cv -> cv.getPropertyPath().toString()) | |
| 55 | + .contains("sUserName", "sPassword"); | |
| 56 | + } | |
| 57 | +} | ... | ... |