main
			
			
		
		
							parent
							
								
									76ed47c1b3
								
							
						
					
					
						commit
						7f8fabd46e
					
				@ -1,6 +1,6 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.data.dao.mapper; | 
				
			||||
package wusthelper.data.dao.mapper; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.wusthelper.data.entity.Student; | 
				
			||||
import wusthelper.data.entity.Student; | 
				
			||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; | 
				
			||||
import org.apache.ibatis.annotations.Mapper; | 
				
			||||
 | 
				
			||||
@ -1,23 +0,0 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.web.api.v2.undergrade; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.wusthelper.web.service.campus.undergrad.UndergradCookieService; | 
				
			||||
import cn.wustlinghang.wusthelper.web.response.Response; | 
				
			||||
import org.springframework.web.bind.annotation.PostMapping; | 
				
			||||
import org.springframework.web.bind.annotation.RequestMapping; | 
				
			||||
import org.springframework.web.bind.annotation.RestController; | 
				
			||||
 | 
				
			||||
@RestController | 
				
			||||
@RequestMapping("/jwc") | 
				
			||||
public class UndergradController { | 
				
			||||
    private final UndergradCookieService undergradCookieService; | 
				
			||||
 | 
				
			||||
    public UndergradController(UndergradCookieService undergradCookieService) { | 
				
			||||
        this.undergradCookieService = undergradCookieService; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    @PostMapping("/login") | 
				
			||||
    public Response<String> login() { | 
				
			||||
        String cookie = undergradCookieService.getLoginCookie("202118194039", "-96387ee"); | 
				
			||||
        return Response.success(cookie); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -1,30 +0,0 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.web.service.campus.undergrad; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.wusthelper.web.rpc.undergrad.StudentInfoRemote; | 
				
			||||
import cn.wustlinghang.wusthelper.web.entity.CookieType; | 
				
			||||
import cn.wustlinghang.wusthelper.web.service.cookie.CookieManager; | 
				
			||||
import cn.wustlinghang.mywust.data.global.StudentInfo; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.response.RpcCommonResponseCode; | 
				
			||||
import org.springframework.stereotype.Service; | 
				
			||||
 | 
				
			||||
@Service | 
				
			||||
public class StudentInfoService { | 
				
			||||
    private final StudentInfoRemote studentInfoRemote; | 
				
			||||
    private final CookieManager cookieManager; | 
				
			||||
 | 
				
			||||
    public StudentInfoService(StudentInfoRemote studentInfoRemote, CookieManager cookieManager) { | 
				
			||||
        this.studentInfoRemote = studentInfoRemote; | 
				
			||||
        this.cookieManager = cookieManager; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public StudentInfo getStudentInfo(String user) { | 
				
			||||
        String cookie = cookieManager.getCookie(user, CookieType.UNDERGRAD); | 
				
			||||
        var response = studentInfoRemote.get(cookie); | 
				
			||||
        if (response.code() != RpcCommonResponseCode.SUCCESS.getCode()) { | 
				
			||||
            return null; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        // todo 异步存用户课表,异常判断等等
 | 
				
			||||
        return response.data(); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -1,21 +0,0 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.web.service.campus.undergrad; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.wusthelper.web.rpc.undergrad.CookieRemote; | 
				
			||||
import org.springframework.stereotype.Service; | 
				
			||||
 | 
				
			||||
@Service | 
				
			||||
public class UndergradCookieService { | 
				
			||||
    private final CookieRemote cookieRemote; | 
				
			||||
 | 
				
			||||
    public UndergradCookieService(CookieRemote cookieRemote) { | 
				
			||||
        this.cookieRemote = cookieRemote; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public String getLoginCookie(String username, String password) { | 
				
			||||
        return cookieRemote.login(username, password).data(); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public Boolean checkCookie(String cookie) { | 
				
			||||
        return cookieRemote.verify(cookie).data(); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -1,62 +0,0 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.web.service.cookie; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.wusthelper.web.entity.CookieType; | 
				
			||||
import cn.wustlinghang.wusthelper.web.service.campus.undergrad.UndergradCookieService; | 
				
			||||
import com.github.benmanes.caffeine.cache.Cache; | 
				
			||||
import com.github.benmanes.caffeine.cache.Caffeine; | 
				
			||||
import org.springframework.context.annotation.Scope; | 
				
			||||
import org.springframework.stereotype.Service; | 
				
			||||
 | 
				
			||||
import java.util.concurrent.TimeUnit; | 
				
			||||
 | 
				
			||||
@Service | 
				
			||||
@Scope("singleton") | 
				
			||||
public class CookieManager { | 
				
			||||
    private static final Cache<String, String> cookiePool = Caffeine.newBuilder() | 
				
			||||
            .expireAfterWrite(2, TimeUnit.HOURS) | 
				
			||||
            .initialCapacity(256) | 
				
			||||
            .maximumSize(2048) | 
				
			||||
            .build(); | 
				
			||||
 | 
				
			||||
    private final UndergradCookieService undergradCookieService; | 
				
			||||
 | 
				
			||||
    public CookieManager(UndergradCookieService undergradCookieService) { | 
				
			||||
        this.undergradCookieService = undergradCookieService; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public String getCookie(String username, CookieType cookieType) { | 
				
			||||
        return getCookie(username, cookieType, false); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public String getCookie(String username, CookieType cookieType, boolean forceRefresh) { | 
				
			||||
        String cacheKey = String.format("%s:%d", username, cookieType.getCode()); | 
				
			||||
        String cookie = cookiePool.getIfPresent(cacheKey); | 
				
			||||
 | 
				
			||||
        boolean valid = cookie != null && checkCookie(cookie, cookieType) && !forceRefresh; | 
				
			||||
        if (valid) { | 
				
			||||
            return cookie; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        cookie = this.refreshCookie(username, cookieType); | 
				
			||||
        cookiePool.put(cacheKey, cookie); | 
				
			||||
 | 
				
			||||
        return cookie; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public boolean checkCookie(String cookie, CookieType cookieType) { | 
				
			||||
        return switch (cookieType) { | 
				
			||||
            case UNDERGRAD -> undergradCookieService.checkCookie(cookie); | 
				
			||||
            case GRADUATE -> undergradCookieService.checkCookie(cookie); | 
				
			||||
            default -> false; | 
				
			||||
        }; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public String refreshCookie(String username, CookieType cookieType) { | 
				
			||||
        String password = ""; | 
				
			||||
        return switch (cookieType) { | 
				
			||||
            case UNDERGRAD -> undergradCookieService.getLoginCookie(username, password); | 
				
			||||
            case GRADUATE -> undergradCookieService.getLoginCookie(username, password); | 
				
			||||
            default -> null; | 
				
			||||
        }; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -1,4 +1,4 @@ | 
				
			||||
package cn.wustlinghang.wusthelper; | 
				
			||||
package wusthelper; | 
				
			||||
 | 
				
			||||
import org.mybatis.spring.annotation.MapperScan; | 
				
			||||
import org.springframework.boot.SpringApplication; | 
				
			||||
@ -1,4 +1,4 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.web.api; | 
				
			||||
package wusthelper.web.api; | 
				
			||||
 | 
				
			||||
import org.springframework.stereotype.Controller; | 
				
			||||
import org.springframework.web.bind.annotation.RequestMapping; | 
				
			||||
@ -0,0 +1,81 @@ | 
				
			||||
package wusthelper.web.api.v2; | 
				
			||||
 | 
				
			||||
import com.auth0.jwt.JWT; | 
				
			||||
import com.auth0.jwt.algorithms.Algorithm; | 
				
			||||
import com.auth0.jwt.exceptions.JWTVerificationException; | 
				
			||||
import lombok.extern.slf4j.Slf4j; | 
				
			||||
 | 
				
			||||
import java.time.Duration; | 
				
			||||
import java.util.Date; | 
				
			||||
 | 
				
			||||
@Slf4j | 
				
			||||
public class Token { | 
				
			||||
 | 
				
			||||
    private final static String SECRET = "LingHangStudio.WustHelper"; | 
				
			||||
 | 
				
			||||
    private final static long EXPIRE_SCD = Duration.ofDays(3).toSeconds(); | 
				
			||||
 | 
				
			||||
    private static final Algorithm jwtAlgorithm = Algorithm.HMAC256(SECRET); | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * 签发Token | 
				
			||||
     * | 
				
			||||
     * @return | 
				
			||||
     */ | 
				
			||||
    public static String signToken(Long uid, String studentNumber) { | 
				
			||||
        try { | 
				
			||||
            Date now = new Date(); | 
				
			||||
            Date expireAt = new Date(now.getTime() + EXPIRE_SCD); | 
				
			||||
 | 
				
			||||
            return JWT.create() | 
				
			||||
                    .withClaim("StuId", uid.toString()) | 
				
			||||
                    .withClaim("StuNum", studentNumber) | 
				
			||||
                    .withIssuedAt(now) | 
				
			||||
                    .withExpiresAt(expireAt) | 
				
			||||
                    .sign(jwtAlgorithm); | 
				
			||||
        } catch (Exception e) { | 
				
			||||
            log.error("[{}]:Token签发工具类>签发Token异常, 空指针异常: uid={},studentNumber={}", | 
				
			||||
                    Thread.currentThread().getStackTrace()[1].getMethodName(), | 
				
			||||
                    uid, studentNumber); | 
				
			||||
            throw new RuntimeException("[JwtUtil.signToken()]"); | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * 校验Token | 
				
			||||
     * | 
				
			||||
     * @param token | 
				
			||||
     * @return | 
				
			||||
     */ | 
				
			||||
    public static boolean verifyToken(String token) { | 
				
			||||
        try { | 
				
			||||
            JWT.require(jwtAlgorithm) | 
				
			||||
                    .build() | 
				
			||||
                    .verify(token); | 
				
			||||
        } catch (JWTVerificationException e) { | 
				
			||||
            return false; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return true; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * Token 负载StuId | 
				
			||||
     * | 
				
			||||
     * @param token | 
				
			||||
     * @return | 
				
			||||
     */ | 
				
			||||
    public static String getUid(String token) { | 
				
			||||
        return JWT.decode(token).getClaim("StuId").asString(); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * Token 负载StuNum | 
				
			||||
     * | 
				
			||||
     * @param token | 
				
			||||
     * @return | 
				
			||||
     */ | 
				
			||||
    public static String getStudentNumber(String token) { | 
				
			||||
        return JWT.decode(token).getClaim("StuNum").asString(); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,5 @@ | 
				
			||||
package wusthelper.web.api.v2.undergrade; | 
				
			||||
 | 
				
			||||
public class UndergradController { | 
				
			||||
 | 
				
			||||
} | 
				
			||||
@ -0,0 +1,30 @@ | 
				
			||||
package wusthelper.web.api.v2.undergrade; | 
				
			||||
 | 
				
			||||
import org.springframework.web.bind.annotation.*; | 
				
			||||
import wusthelper.internal.rpc.response.RpcCommonResponseCode; | 
				
			||||
import wusthelper.web.api.v2.Token; | 
				
			||||
import wusthelper.web.response.Response; | 
				
			||||
import wusthelper.web.service.campus.GeneralUserService; | 
				
			||||
import wusthelper.web.service.campus.undergrad.UndergradCookieService; | 
				
			||||
 | 
				
			||||
@RestController | 
				
			||||
@RequestMapping("/jwc") | 
				
			||||
public class UndergradLoginController { | 
				
			||||
    private final GeneralUserService generalUserService; | 
				
			||||
 | 
				
			||||
    public UndergradLoginController(GeneralUserService generalUserService) { | 
				
			||||
        this.generalUserService = generalUserService; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    @PostMapping("/login") | 
				
			||||
    public Response<String> login(@RequestParam(value = "username") String username, | 
				
			||||
                                  @RequestParam(value = "jwcPwd") String password, | 
				
			||||
                                  @RequestHeader(name = "Platform", required = false) String platform) { | 
				
			||||
 | 
				
			||||
        var user = generalUserService.login(username, password, GeneralUserService.UserType.Undergrad); | 
				
			||||
 | 
				
			||||
        String token = Token.signToken(user.getId(), user.getStuNum()); | 
				
			||||
 | 
				
			||||
        return Response.success(token); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -1,4 +1,4 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.web.configure; | 
				
			||||
package wusthelper.web.configure; | 
				
			||||
 | 
				
			||||
import com.github.benmanes.caffeine.cache.Cache; | 
				
			||||
import com.github.benmanes.caffeine.cache.Caffeine; | 
				
			||||
@ -0,0 +1,12 @@ | 
				
			||||
package wusthelper.web.configure; | 
				
			||||
 | 
				
			||||
import lombok.Data; | 
				
			||||
import org.springframework.boot.context.properties.ConfigurationProperties; | 
				
			||||
import org.springframework.stereotype.Component; | 
				
			||||
 | 
				
			||||
@Data | 
				
			||||
@Component | 
				
			||||
@ConfigurationProperties("wusthelper") | 
				
			||||
public class GlobalConfigureItems { | 
				
			||||
    private String passwordEncodeKey; | 
				
			||||
} | 
				
			||||
@ -0,0 +1,21 @@ | 
				
			||||
package wusthelper.web.configure; | 
				
			||||
 | 
				
			||||
import org.springframework.context.annotation.Bean; | 
				
			||||
import org.springframework.context.annotation.Configuration; | 
				
			||||
import wusthelper.web.util.PasswordCodec; | 
				
			||||
 | 
				
			||||
@Configuration | 
				
			||||
public class PasswordCodecConfigure { | 
				
			||||
    private final GlobalConfigureItems globalConfigureItems; | 
				
			||||
 | 
				
			||||
    public PasswordCodecConfigure(GlobalConfigureItems globalConfigureItems) { | 
				
			||||
        this.globalConfigureItems = globalConfigureItems; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    @Bean | 
				
			||||
    public PasswordCodec passwordCodec() { | 
				
			||||
        String key = globalConfigureItems.getPasswordEncodeKey(); | 
				
			||||
 | 
				
			||||
        return new PasswordCodec(key); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -1,12 +1,12 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.web.entity; | 
				
			||||
package wusthelper.web.data.entity; | 
				
			||||
 | 
				
			||||
import java.util.StringJoiner; | 
				
			||||
 | 
				
			||||
public enum CookieType { | 
				
			||||
    UNDERGRAD(0, "本科生"), | 
				
			||||
    GRADUATE(1, "研究生"), | 
				
			||||
    LIBRARY(2, "图书馆"), | 
				
			||||
    PHYSICS(3, "物理实验"),; | 
				
			||||
    Undergrad(0, "本科生"), | 
				
			||||
    Graduate(1, "研究生"), | 
				
			||||
    Library(2, "图书馆"), | 
				
			||||
    Physics(3, "物理实验"),; | 
				
			||||
 | 
				
			||||
    private final int code; | 
				
			||||
 | 
				
			||||
@ -0,0 +1,18 @@ | 
				
			||||
package wusthelper.web.rpc.graduate; | 
				
			||||
 | 
				
			||||
import org.springframework.cloud.openfeign.FeignClient; | 
				
			||||
import org.springframework.web.bind.annotation.GetMapping; | 
				
			||||
import org.springframework.web.bind.annotation.RequestParam; | 
				
			||||
import wusthelper.internal.rpc.response.RpcResponseDto; | 
				
			||||
 | 
				
			||||
@FeignClient(name = "wusthelper.graduate", contextId = "cookie") | 
				
			||||
public interface GraduateCookieRemote { | 
				
			||||
    String COOKIE_ROOT_PATH = "/cookie"; | 
				
			||||
 | 
				
			||||
    @GetMapping(COOKIE_ROOT_PATH) | 
				
			||||
    RpcResponseDto<String> login(@RequestParam("username") String username, | 
				
			||||
                                 @RequestParam("password") String password); | 
				
			||||
 | 
				
			||||
    @GetMapping(COOKIE_ROOT_PATH + "/verify") | 
				
			||||
    RpcResponseDto<Boolean> verify(@RequestParam("cookie") String cookie); | 
				
			||||
} | 
				
			||||
@ -0,0 +1,23 @@ | 
				
			||||
package wusthelper.web.rpc.graduate; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.data.global.StudentInfo; | 
				
			||||
import jakarta.validation.constraints.NotNull; | 
				
			||||
import org.springframework.cloud.openfeign.FeignClient; | 
				
			||||
import org.springframework.web.bind.annotation.GetMapping; | 
				
			||||
import org.springframework.web.bind.annotation.PostMapping; | 
				
			||||
import org.springframework.web.bind.annotation.RequestParam; | 
				
			||||
import wusthelper.internal.rpc.response.RpcResponseDto; | 
				
			||||
 | 
				
			||||
@FeignClient(name = "wusthelper.graduate", contextId = "studentInfo") | 
				
			||||
public interface GraduateStudentInfoRemote { | 
				
			||||
    String ROOT_PATH = "/student_info"; | 
				
			||||
 | 
				
			||||
    @GetMapping(ROOT_PATH) | 
				
			||||
    RpcResponseDto<StudentInfo> get(@RequestParam("cookie") String cookie); | 
				
			||||
 | 
				
			||||
    @GetMapping(ROOT_PATH + "/agent") | 
				
			||||
    RpcResponseDto<String> agent(@RequestParam("cookie") @NotNull String cookie); | 
				
			||||
 | 
				
			||||
    @PostMapping(ROOT_PATH + "/parse") | 
				
			||||
    RpcResponseDto<StudentInfo> parse(String html); | 
				
			||||
} | 
				
			||||
@ -1,7 +1,7 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.web.rpc.undergrad; | 
				
			||||
package wusthelper.web.rpc.undergrad; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.data.global.Course; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.response.RpcResponseDto; | 
				
			||||
import wusthelper.internal.rpc.response.RpcResponseDto; | 
				
			||||
import jakarta.validation.constraints.NotNull; | 
				
			||||
import org.springframework.cloud.openfeign.FeignClient; | 
				
			||||
import org.springframework.web.bind.annotation.GetMapping; | 
				
			||||
@ -1,6 +1,6 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.web.rpc.undergrad; | 
				
			||||
package wusthelper.web.rpc.undergrad; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.response.RpcResponseDto; | 
				
			||||
import wusthelper.internal.rpc.response.RpcResponseDto; | 
				
			||||
import jakarta.validation.constraints.NotNull; | 
				
			||||
import org.springframework.cloud.openfeign.FeignClient; | 
				
			||||
import org.springframework.web.bind.annotation.GetMapping; | 
				
			||||
@ -1,7 +1,7 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.web.rpc.undergrad; | 
				
			||||
package wusthelper.web.rpc.undergrad; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.data.undergrad.ExamDelayApplication; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.response.RpcResponseDto; | 
				
			||||
import wusthelper.internal.rpc.response.RpcResponseDto; | 
				
			||||
import jakarta.validation.constraints.NotNull; | 
				
			||||
import org.springframework.cloud.openfeign.FeignClient; | 
				
			||||
import org.springframework.web.bind.annotation.GetMapping; | 
				
			||||
@ -1,7 +1,7 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.web.rpc.undergrad; | 
				
			||||
package wusthelper.web.rpc.undergrad; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.data.global.Score; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.response.RpcResponseDto; | 
				
			||||
import wusthelper.internal.rpc.response.RpcResponseDto; | 
				
			||||
import jakarta.validation.constraints.NotNull; | 
				
			||||
import org.springframework.cloud.openfeign.FeignClient; | 
				
			||||
import org.springframework.web.bind.annotation.GetMapping; | 
				
			||||
@ -1,6 +1,6 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.web.rpc.undergrad; | 
				
			||||
package wusthelper.web.rpc.undergrad; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.response.RpcResponseDto; | 
				
			||||
import wusthelper.internal.rpc.response.RpcResponseDto; | 
				
			||||
import jakarta.validation.constraints.NotNull; | 
				
			||||
import org.springframework.cloud.openfeign.FeignClient; | 
				
			||||
import org.springframework.web.bind.annotation.GetMapping; | 
				
			||||
@ -1,12 +1,12 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.web.rpc.undergrad; | 
				
			||||
package wusthelper.web.rpc.undergrad; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.response.RpcResponseDto; | 
				
			||||
import wusthelper.internal.rpc.response.RpcResponseDto; | 
				
			||||
import org.springframework.cloud.openfeign.FeignClient; | 
				
			||||
import org.springframework.web.bind.annotation.GetMapping; | 
				
			||||
import org.springframework.web.bind.annotation.RequestParam; | 
				
			||||
 | 
				
			||||
@FeignClient(name = "wusthelper.undergrad", contextId = "cookie") | 
				
			||||
public interface CookieRemote { | 
				
			||||
public interface UndergradCookieRemote { | 
				
			||||
    String COOKIE_ROOT_PATH = "/cookie"; | 
				
			||||
 | 
				
			||||
    @GetMapping(COOKIE_ROOT_PATH) | 
				
			||||
@ -0,0 +1,116 @@ | 
				
			||||
package wusthelper.web.service.campus; | 
				
			||||
 | 
				
			||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | 
				
			||||
import com.github.yitter.idgen.YitIdHelper; | 
				
			||||
import org.springframework.stereotype.Service; | 
				
			||||
import wusthelper.code.ServiceCode; | 
				
			||||
import wusthelper.data.dao.mapper.StudentMapper; | 
				
			||||
import wusthelper.data.entity.Student; | 
				
			||||
import wusthelper.web.data.entity.CookieType; | 
				
			||||
import wusthelper.web.exception.ServiceException; | 
				
			||||
import wusthelper.web.rpc.graduate.GraduateStudentInfoRemote; | 
				
			||||
import wusthelper.web.rpc.undergrad.UndergradStudentInfoRemote; | 
				
			||||
import wusthelper.web.service.campus.graduate.GraduateCookieService; | 
				
			||||
import wusthelper.web.service.campus.undergrad.UndergradCookieService; | 
				
			||||
import wusthelper.web.service.cookie.CookieManager; | 
				
			||||
import wusthelper.web.util.Converter; | 
				
			||||
import wusthelper.web.util.PasswordCodec; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * 通用的用户信息服务,包括登录和(已存储的)用户信息获取等,同时自动存入新用户信息 | 
				
			||||
 */ | 
				
			||||
@Service | 
				
			||||
public class GeneralUserService { | 
				
			||||
    private final StudentMapper studentMapper; | 
				
			||||
    private final PasswordCodec passwordCodec; | 
				
			||||
 | 
				
			||||
    private final UndergradCookieService undergradCookieService; | 
				
			||||
    private final GraduateCookieService graduateCookieService; | 
				
			||||
 | 
				
			||||
    private final GraduateStudentInfoRemote graduateStudentInfoRemote; | 
				
			||||
    private final UndergradStudentInfoRemote undergradStudentInfoRemote; | 
				
			||||
 | 
				
			||||
 | 
				
			||||
    public GeneralUserService(StudentMapper studentMapper, | 
				
			||||
                              PasswordCodec passwordCodec, | 
				
			||||
 | 
				
			||||
                              UndergradCookieService undergradCookieService, | 
				
			||||
                              GraduateCookieService graduateCookieService, | 
				
			||||
 | 
				
			||||
                              GraduateStudentInfoRemote graduateStudentInfoRemote, | 
				
			||||
                              UndergradStudentInfoRemote undergradStudentInfoRemote) { | 
				
			||||
 | 
				
			||||
        this.studentMapper = studentMapper; | 
				
			||||
        this.passwordCodec = passwordCodec; | 
				
			||||
 | 
				
			||||
        this.undergradCookieService = undergradCookieService; | 
				
			||||
        this.graduateCookieService = graduateCookieService; | 
				
			||||
 | 
				
			||||
        this.graduateStudentInfoRemote = graduateStudentInfoRemote; | 
				
			||||
        this.undergradStudentInfoRemote = undergradStudentInfoRemote; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public enum UserType {Undergrad, Graduate} | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * 登录验证并获取用户信息,同时自动存库 | 
				
			||||
     * | 
				
			||||
     * @param username 用户名(即学号) | 
				
			||||
     * @param password 密码(明文原文) | 
				
			||||
     * @param userType 用户类型,现在有本科生和研究生 | 
				
			||||
     * @return 用户信息 | 
				
			||||
     */ | 
				
			||||
    public Student login(String username, String password, UserType userType) { | 
				
			||||
        var cookie = switch (userType) { | 
				
			||||
            case Undergrad -> undergradCookieService.getLoginCookie(username, password); | 
				
			||||
            case Graduate -> graduateCookieService.getLoginCookie(username, password); | 
				
			||||
        }; | 
				
			||||
 | 
				
			||||
        var cookieType = switch (userType) { | 
				
			||||
            case Undergrad -> CookieType.Undergrad; | 
				
			||||
            case Graduate -> CookieType.Graduate; | 
				
			||||
        }; | 
				
			||||
 | 
				
			||||
        // 保存cookie,并获取用户信息并存库(基本的操作,非异步,信息获取失败意味登陆失败)
 | 
				
			||||
        CookieManager.store(username, cookie, cookieType); | 
				
			||||
        return this.saveOrUpdateUser(username, cookie, password, userType); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    private Student saveOrUpdateUser(String username, String cookie, String password, UserType userType) { | 
				
			||||
        var rpcResp = switch (userType) { | 
				
			||||
            case Undergrad -> undergradStudentInfoRemote.get(cookie); | 
				
			||||
            case Graduate -> graduateStudentInfoRemote.get(cookie); | 
				
			||||
        }; | 
				
			||||
 | 
				
			||||
        if (rpcResp.code() != ServiceCode.Ok) { | 
				
			||||
            ServiceException.of(rpcResp.code()); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        var studentInfo = rpcResp.data(); | 
				
			||||
        var student = Converter.convert(studentInfo); | 
				
			||||
        if (student.getStuNum() == null) { | 
				
			||||
            student.setStuNum(username); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        var query = new QueryWrapper<Student>() | 
				
			||||
                .eq("stu_num", username) | 
				
			||||
                .eq("deleted", 0); | 
				
			||||
 | 
				
			||||
        // (按学号)检查用户信息是否已经存在数据库中,已存在则更新,否则新增信息
 | 
				
			||||
        var studentExists = studentMapper.exists(query); | 
				
			||||
        if (studentExists) { | 
				
			||||
            studentMapper.update(student, query); | 
				
			||||
        } else { | 
				
			||||
            student.setId(YitIdHelper.nextId()); | 
				
			||||
            var encrypted = passwordCodec.encode(password); | 
				
			||||
            student.setJwcPwd(encrypted); | 
				
			||||
            if (userType == UserType.Undergrad) { | 
				
			||||
                student.setLibPwd(encrypted); | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            studentMapper.insert(student); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return student; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,28 @@ | 
				
			||||
package wusthelper.web.service.campus.graduate; | 
				
			||||
 | 
				
			||||
import org.springframework.stereotype.Service; | 
				
			||||
import wusthelper.code.ServiceCode; | 
				
			||||
import wusthelper.web.exception.ServiceException; | 
				
			||||
import wusthelper.web.rpc.graduate.GraduateCookieRemote; | 
				
			||||
 | 
				
			||||
@Service | 
				
			||||
public class GraduateCookieService { | 
				
			||||
    private final GraduateCookieRemote graduateCookieRemote; | 
				
			||||
 | 
				
			||||
    public GraduateCookieService(GraduateCookieRemote graduateCookieRemote) { | 
				
			||||
        this.graduateCookieRemote = graduateCookieRemote; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public String getLoginCookie(String username, String password) throws ServiceException { | 
				
			||||
        var rpcResp = graduateCookieRemote.login(username, password); | 
				
			||||
        if (rpcResp.code() != ServiceCode.Ok) { | 
				
			||||
            ServiceException.of(rpcResp.code()); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return rpcResp.data(); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public Boolean checkCookie(String cookie) { | 
				
			||||
        return graduateCookieRemote.verify(cookie).data(); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,46 @@ | 
				
			||||
package wusthelper.web.service.campus.graduate; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.data.global.StudentInfo; | 
				
			||||
import org.springframework.stereotype.Service; | 
				
			||||
import wusthelper.code.ServiceCode; | 
				
			||||
import wusthelper.web.data.entity.CookieType; | 
				
			||||
import wusthelper.web.exception.ServiceException; | 
				
			||||
import wusthelper.web.rpc.graduate.GraduateStudentInfoRemote; | 
				
			||||
import wusthelper.web.service.cookie.CookieManager; | 
				
			||||
import wusthelper.web.service.student.StudentService; | 
				
			||||
 | 
				
			||||
@Service | 
				
			||||
public class GraduateStudentInfoService { | 
				
			||||
    private final GraduateStudentInfoRemote graduateStudentInfoRemote; | 
				
			||||
 | 
				
			||||
    private final CookieManager cookieManager; | 
				
			||||
 | 
				
			||||
    private final StudentService studentService; | 
				
			||||
 | 
				
			||||
    public GraduateStudentInfoService(GraduateStudentInfoRemote graduateStudentInfoRemote, | 
				
			||||
                                      CookieManager cookieManager, | 
				
			||||
                                      StudentService studentService) { | 
				
			||||
 | 
				
			||||
        this.graduateStudentInfoRemote = graduateStudentInfoRemote; | 
				
			||||
        this.cookieManager = cookieManager; | 
				
			||||
        this.studentService = studentService; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public StudentInfo getStudentInfo(String user) { | 
				
			||||
        String cookie = cookieManager.getCookie(user, CookieType.Graduate); | 
				
			||||
 | 
				
			||||
        return getStudentInfo(user, cookie); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public StudentInfo getStudentInfo(String user, String cookie) { | 
				
			||||
        var response = graduateStudentInfoRemote.get(cookie); | 
				
			||||
        if (response.code() != ServiceCode.Ok) { | 
				
			||||
            ServiceException.of(response.code()); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        var studentInfo = response.data(); | 
				
			||||
 | 
				
			||||
        studentService.saveOrUpdateUserAsync(user, studentInfo); | 
				
			||||
        return studentInfo; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,29 @@ | 
				
			||||
package wusthelper.web.service.campus.undergrad; | 
				
			||||
 | 
				
			||||
import org.springframework.stereotype.Service; | 
				
			||||
import wusthelper.code.ServiceCode; | 
				
			||||
import wusthelper.web.exception.ServiceException; | 
				
			||||
import wusthelper.web.rpc.undergrad.UndergradCookieRemote; | 
				
			||||
 | 
				
			||||
@Service | 
				
			||||
public class UndergradCookieService { | 
				
			||||
 | 
				
			||||
    private final UndergradCookieRemote undergradCookieRemote; | 
				
			||||
 | 
				
			||||
    public UndergradCookieService(UndergradCookieRemote undergradCookieRemote) { | 
				
			||||
        this.undergradCookieRemote = undergradCookieRemote; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public String getLoginCookie(String username, String password) throws ServiceException { | 
				
			||||
        var rpcResp = undergradCookieRemote.login(username, password); | 
				
			||||
        if (rpcResp.code() != ServiceCode.Ok) { | 
				
			||||
            ServiceException.of(rpcResp.code()); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return rpcResp.data(); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public Boolean checkCookie(String cookie) { | 
				
			||||
        return undergradCookieRemote.verify(cookie).data(); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,48 @@ | 
				
			||||
package wusthelper.web.service.campus.undergrad; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.data.global.StudentInfo; | 
				
			||||
import org.springframework.stereotype.Service; | 
				
			||||
import wusthelper.code.ServiceCode; | 
				
			||||
import wusthelper.web.data.entity.CookieType; | 
				
			||||
import wusthelper.web.exception.ServiceException; | 
				
			||||
import wusthelper.web.rpc.undergrad.UndergradStudentInfoRemote; | 
				
			||||
import wusthelper.web.service.cookie.CookieManager; | 
				
			||||
import wusthelper.web.service.student.StudentService; | 
				
			||||
import wusthelper.web.util.PasswordCodec; | 
				
			||||
 | 
				
			||||
@Service | 
				
			||||
public class UndergradStudentInfoService { | 
				
			||||
 | 
				
			||||
    private final UndergradStudentInfoRemote undergradStudentInfoRemote; | 
				
			||||
 | 
				
			||||
    private final CookieManager cookieManager; | 
				
			||||
 | 
				
			||||
    private final StudentService studentService; | 
				
			||||
 | 
				
			||||
    public UndergradStudentInfoService(UndergradStudentInfoRemote undergradStudentInfoRemote, | 
				
			||||
                                       CookieManager cookieManager, | 
				
			||||
                                       StudentService studentService) { | 
				
			||||
 | 
				
			||||
        this.undergradStudentInfoRemote = undergradStudentInfoRemote; | 
				
			||||
        this.cookieManager = cookieManager; | 
				
			||||
        this.studentService = studentService; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public StudentInfo getStudentInfo(String user) { | 
				
			||||
        String cookie = cookieManager.getCookie(user, CookieType.Undergrad); | 
				
			||||
 | 
				
			||||
        return getStudentInfo(user, cookie); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public StudentInfo getStudentInfo(String user, String cookie) { | 
				
			||||
        var rpcResp = undergradStudentInfoRemote.get(cookie); | 
				
			||||
        if (rpcResp.code() != ServiceCode.Ok) { | 
				
			||||
            ServiceException.of(rpcResp.code()); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        var studentInfo = rpcResp.data(); | 
				
			||||
 | 
				
			||||
        studentService.saveOrUpdateUserAsync(user, studentInfo); | 
				
			||||
        return studentInfo; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,100 @@ | 
				
			||||
package wusthelper.web.service.cookie; | 
				
			||||
 | 
				
			||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | 
				
			||||
import wusthelper.code.ServiceCode; | 
				
			||||
import wusthelper.data.dao.mapper.StudentMapper; | 
				
			||||
import wusthelper.data.entity.Student; | 
				
			||||
import wusthelper.web.data.entity.CookieType; | 
				
			||||
import wusthelper.web.exception.ServiceException; | 
				
			||||
import wusthelper.web.service.campus.graduate.GraduateCookieService; | 
				
			||||
import wusthelper.web.service.campus.undergrad.UndergradCookieService; | 
				
			||||
import com.github.benmanes.caffeine.cache.Cache; | 
				
			||||
import com.github.benmanes.caffeine.cache.Caffeine; | 
				
			||||
import org.springframework.context.annotation.Scope; | 
				
			||||
import org.springframework.stereotype.Service; | 
				
			||||
 | 
				
			||||
import java.util.concurrent.TimeUnit; | 
				
			||||
 | 
				
			||||
@Service | 
				
			||||
@Scope("singleton") | 
				
			||||
public class CookieManager { | 
				
			||||
    private static final Cache<String, String> cookiePool = Caffeine.newBuilder() | 
				
			||||
            .expireAfterWrite(2, TimeUnit.HOURS) | 
				
			||||
            .initialCapacity(256) | 
				
			||||
            .maximumSize(2048) | 
				
			||||
            .build(); | 
				
			||||
 | 
				
			||||
    private final UndergradCookieService undergradCookieService; | 
				
			||||
    private final GraduateCookieService graduateCookieService; | 
				
			||||
 | 
				
			||||
    private final StudentMapper studentMapper; | 
				
			||||
 | 
				
			||||
    public CookieManager(UndergradCookieService undergradCookieService, | 
				
			||||
                         GraduateCookieService graduateCookieService, | 
				
			||||
                         StudentMapper studentMapper) { | 
				
			||||
 | 
				
			||||
        this.undergradCookieService = undergradCookieService; | 
				
			||||
        this.graduateCookieService = graduateCookieService; | 
				
			||||
 | 
				
			||||
        this.studentMapper = studentMapper; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public String getCookie(String username, CookieType cookieType) { | 
				
			||||
        return getCookie(username, cookieType, false); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public String getCookie(String username, CookieType cookieType, boolean forceRefresh) { | 
				
			||||
        String cacheKey = String.format("%s:%d", username, cookieType.getCode()); | 
				
			||||
        String cookie = cookiePool.getIfPresent(cacheKey); | 
				
			||||
 | 
				
			||||
        boolean valid = cookie != null && checkCookie(cookie, cookieType) && !forceRefresh; | 
				
			||||
        if (valid) { | 
				
			||||
            return cookie; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        cookie = this.refreshCookie(username, cookieType); | 
				
			||||
        cookiePool.put(cacheKey, cookie); | 
				
			||||
 | 
				
			||||
        return cookie; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static void store(String username, String cookie, CookieType cookieType) { | 
				
			||||
        String cacheKey = String.format("%s:%d", username, cookieType.getCode()); | 
				
			||||
        cookiePool.put(cacheKey, cookie); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public boolean checkCookie(String cookie, CookieType cookieType) { | 
				
			||||
        return switch (cookieType) { | 
				
			||||
            case Undergrad -> undergradCookieService.checkCookie(cookie); | 
				
			||||
            case Graduate -> graduateCookieService.checkCookie(cookie); | 
				
			||||
            default -> false; | 
				
			||||
        }; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public String refreshCookie(String username, CookieType cookieType) { | 
				
			||||
        var student = studentMapper.selectOne(new QueryWrapper<Student>() | 
				
			||||
                .eq("stuNum", username) | 
				
			||||
                .eq("deleted", 0) | 
				
			||||
        ); | 
				
			||||
 | 
				
			||||
        if (student == null) { | 
				
			||||
            ServiceException.of(ServiceCode.UserNotExists); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        String password = switch (cookieType) { | 
				
			||||
            case Undergrad, Graduate -> student.getJwcPwd(); | 
				
			||||
            case Library -> student.getLibPwd(); | 
				
			||||
            case Physics -> student.getWlsyPwd(); | 
				
			||||
        }; | 
				
			||||
 | 
				
			||||
        if (password == null) { | 
				
			||||
            ServiceException.of(ServiceCode.ParamWrong); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return switch (cookieType) { | 
				
			||||
            case Undergrad -> undergradCookieService.getLoginCookie(username, password); | 
				
			||||
            case Graduate -> graduateCookieService.getLoginCookie(username, password); | 
				
			||||
            default -> null; | 
				
			||||
        }; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,46 @@ | 
				
			||||
package wusthelper.web.service.student; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.data.global.StudentInfo; | 
				
			||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | 
				
			||||
import com.github.yitter.idgen.YitIdHelper; | 
				
			||||
import org.springframework.scheduling.annotation.Async; | 
				
			||||
import org.springframework.scheduling.annotation.EnableAsync; | 
				
			||||
import org.springframework.stereotype.Service; | 
				
			||||
import wusthelper.data.dao.mapper.StudentMapper; | 
				
			||||
import wusthelper.data.entity.Student; | 
				
			||||
import wusthelper.web.util.Converter; | 
				
			||||
 | 
				
			||||
import java.util.concurrent.CompletableFuture; | 
				
			||||
 | 
				
			||||
@Service | 
				
			||||
@EnableAsync | 
				
			||||
public class StudentService { | 
				
			||||
    private final StudentMapper studentMapper; | 
				
			||||
 | 
				
			||||
    public StudentService(StudentMapper studentMapper) { | 
				
			||||
        this.studentMapper = studentMapper; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    @Async | 
				
			||||
    public CompletableFuture<Student> saveOrUpdateUserAsync(String username, StudentInfo studentInfo) { | 
				
			||||
        var student = Converter.convert(studentInfo); | 
				
			||||
        if (student.getStuNum() == null) { | 
				
			||||
            student.setStuNum(username); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        var query = new QueryWrapper<Student>() | 
				
			||||
                .eq("stuNum", username) | 
				
			||||
                .eq("deleted", 0); | 
				
			||||
 | 
				
			||||
        // (按学号)检查用户信息是否已经存在数据库中,已存在则更新,否则新增信息
 | 
				
			||||
        var studentExists = studentMapper.exists(query); | 
				
			||||
        if (studentExists) { | 
				
			||||
            studentMapper.update(student, query); | 
				
			||||
        } else { | 
				
			||||
            student.setId(YitIdHelper.nextId()); | 
				
			||||
            studentMapper.insert(student); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return CompletableFuture.completedFuture(student); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,29 @@ | 
				
			||||
package wusthelper.web.util; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.data.global.StudentInfo; | 
				
			||||
import wusthelper.data.entity.Student; | 
				
			||||
 | 
				
			||||
public class Converter { | 
				
			||||
    public static Student convert(StudentInfo studentInfo) { | 
				
			||||
        Student student = new Student(); | 
				
			||||
//        student.setId();
 | 
				
			||||
        student.setStuNum(studentInfo.getStudentNumber()); | 
				
			||||
        student.setStuName(studentInfo.getName()); | 
				
			||||
//        student.setJwcPwd();
 | 
				
			||||
//        student.setWlsyPwd();
 | 
				
			||||
//        student.setCollegeId();
 | 
				
			||||
//        student.setMajorId();
 | 
				
			||||
//        student.setClassId();
 | 
				
			||||
        student.setBirthday(studentInfo.getBirthday()); | 
				
			||||
        student.setSex(studentInfo.getSex()); | 
				
			||||
        student.setNation(studentInfo.getNationality()); | 
				
			||||
        student.setNativePlace(studentInfo.getHometown()); | 
				
			||||
//        student.setNickName();
 | 
				
			||||
//        student.setPhone();
 | 
				
			||||
//        student.setEmail();
 | 
				
			||||
//        student.setQqNum();
 | 
				
			||||
//        student.setWechatNum();
 | 
				
			||||
//        student.setPlatform();
 | 
				
			||||
        return student; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -1,6 +1,6 @@ | 
				
			||||
package cn.wustlinghang.wusthelper; | 
				
			||||
package wusthelper; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.wusthelper.data.dao.mapper.StudentMapper; | 
				
			||||
import wusthelper.data.dao.mapper.StudentMapper; | 
				
			||||
import org.junit.jupiter.api.Test; | 
				
			||||
import org.junit.jupiter.api.extension.ExtendWith; | 
				
			||||
import org.springframework.beans.factory.annotation.Autowired; | 
				
			||||
@ -1,29 +1,48 @@ | 
				
			||||
package cn.wustlinghang.wusthelper; | 
				
			||||
package wusthelper; | 
				
			||||
 | 
				
			||||
import lombok.extern.slf4j.Slf4j; | 
				
			||||
import org.junit.jupiter.api.Test; | 
				
			||||
import org.junit.jupiter.api.extension.ExtendWith; | 
				
			||||
import org.mybatis.spring.annotation.MapperScan; | 
				
			||||
import org.springframework.boot.autoconfigure.SpringBootApplication; | 
				
			||||
import org.springframework.boot.test.context.SpringBootTest; | 
				
			||||
import org.springframework.cloud.openfeign.EnableFeignClients; | 
				
			||||
import org.springframework.context.annotation.Configuration; | 
				
			||||
import org.springframework.scheduling.annotation.EnableAsync; | 
				
			||||
import org.springframework.scheduling.annotation.EnableScheduling; | 
				
			||||
import org.springframework.test.context.TestPropertySource; | 
				
			||||
import org.springframework.test.context.junit.jupiter.SpringExtension; | 
				
			||||
import wusthelper.web.api.v2.Token; | 
				
			||||
 | 
				
			||||
@Slf4j | 
				
			||||
@EnableAsync | 
				
			||||
@Configuration | 
				
			||||
@EnableScheduling | 
				
			||||
@ExtendWith(SpringExtension.class) | 
				
			||||
@EnableFeignClients(basePackages = {"cn.wustlinghang.wusthelper.web.rpc"}) | 
				
			||||
@EnableFeignClients(basePackages = {"wusthelper.web.rpc"}) | 
				
			||||
@TestPropertySource(properties = { | 
				
			||||
        "spring.config.location=classpath:application-test.yml" | 
				
			||||
}) | 
				
			||||
@SpringBootApplication(scanBasePackages = { | 
				
			||||
        // 指定springboot的bean扫描路径,有新增请及时更新
 | 
				
			||||
        "cn.wustlinghang.wusthelper.data", | 
				
			||||
        "cn.wustlinghang.wusthelper.web", | 
				
			||||
        "wusthelper.data", | 
				
			||||
        "wusthelper.web", | 
				
			||||
}) | 
				
			||||
@MapperScan("cn.wustlinghang.wusthelper.data.dao.mapper") | 
				
			||||
public class TestMain { | 
				
			||||
    @Test | 
				
			||||
    public void jwtTest() { | 
				
			||||
        String token = Token.signToken(1233487L, "202118194039"); | 
				
			||||
        log.info(token); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static void main(String[] args) { | 
				
			||||
        String token = Token.signToken(1233487L, "202118194039"); | 
				
			||||
        boolean valid = Token.verifyToken(token); | 
				
			||||
        var uid = Token.getUid(token); | 
				
			||||
        var studentNumber = Token.getStudentNumber(token); | 
				
			||||
        log.info(token); | 
				
			||||
        log.info("{}", valid); | 
				
			||||
        log.info(uid); | 
				
			||||
        log.info(studentNumber); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -1,34 +0,0 @@ | 
				
			||||
/* | 
				
			||||
 * Class created by lensfrex. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
package cn.wustlinghang.wusthelper.internal.rpc.response; | 
				
			||||
 | 
				
			||||
public enum RpcCommonResponseCode { | 
				
			||||
    SUCCESS(20000, "成功"), | 
				
			||||
    REQUEST_TOO_FAST(20001, "技能冷却中..."), | 
				
			||||
    INVALID_REQUEST(30000, "非法请求"), | 
				
			||||
    PARAM_WRONG(30001, "参数错误"), | 
				
			||||
    PERMISSION_DENIED(40000, "权限不足"), | 
				
			||||
    TOKEN_EXPIRED(40001, "token过期"), | 
				
			||||
    TOKEN_INVALID(40002, "token无效"), | 
				
			||||
    SERVER_INTERNAL_ERROR(50000, "服务器内部错误"), | 
				
			||||
    API_NOT_IMPLEMENT(0, "接口未实现"),; | 
				
			||||
 | 
				
			||||
    private final int code; | 
				
			||||
 | 
				
			||||
    private final String message; | 
				
			||||
 | 
				
			||||
    RpcCommonResponseCode(int code, String message) { | 
				
			||||
        this.code = code; | 
				
			||||
        this.message = message; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public int getCode() { | 
				
			||||
        return code; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public String getMessage() { | 
				
			||||
        return message; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -1,28 +0,0 @@ | 
				
			||||
/* | 
				
			||||
 * Class created by lensfrex. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
package cn.wustlinghang.wusthelper.web.response; | 
				
			||||
 | 
				
			||||
public enum ResponseCode { | 
				
			||||
    SUCCESS(0, "成功"), | 
				
			||||
    SERVER_INTERNAL_ERROR(-2, "服务器内部错误"), | 
				
			||||
    API_NOT_IMPLEMENT(-1, "接口未实现"); | 
				
			||||
 | 
				
			||||
    private final int code; | 
				
			||||
 | 
				
			||||
    private final String message; | 
				
			||||
 | 
				
			||||
    ResponseCode(int code, String message) { | 
				
			||||
        this.code = code; | 
				
			||||
        this.message = message; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public int getCode() { | 
				
			||||
        return code; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public String getMessage() { | 
				
			||||
        return message; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,147 @@ | 
				
			||||
package wusthelper.code; | 
				
			||||
 | 
				
			||||
import java.util.HashMap; | 
				
			||||
import java.util.Map; | 
				
			||||
 | 
				
			||||
public class ServiceCode { | 
				
			||||
    public static final int Ok                  = 0;  // ok
 | 
				
			||||
    public static final int ServerInternalError = -2; // 服务器内部错误
 | 
				
			||||
    public static final int ApiNotImplement     = -1; // 接口未实现
 | 
				
			||||
 | 
				
			||||
    // 所有模块共用
 | 
				
			||||
    public static final int Unknown         = 10_000; // 未知错误
 | 
				
			||||
    public static final int RequestInvalid  = 10_001; // 请求无效
 | 
				
			||||
    public static final int ParamWrong      = 10_002; // 请求无效
 | 
				
			||||
    public static final int CookieInvalid   = 10_003; // 提供的cookie无效
 | 
				
			||||
    public static final int NetworkError    = 10_004; // 网络错误
 | 
				
			||||
    public static final int RpcError        = 10_005; // 上游RPC错误
 | 
				
			||||
    public static final int ParseError      = 10_006; // 解析错误
 | 
				
			||||
 | 
				
			||||
    // 主模块
 | 
				
			||||
    public static final int UserNotExists = 20_001; // 用户不存在
 | 
				
			||||
 | 
				
			||||
    // 本科生
 | 
				
			||||
    public static final int UndergradUserNotExists          = 30_001; // 本科生:用户不存在
 | 
				
			||||
    public static final int UndergradUserBanned             = 30_002; // 本科生:封号
 | 
				
			||||
    public static final int UndergradUserDisabled           = 30_003; // 本科生:用户账号禁用
 | 
				
			||||
    public static final int UndergradPasswordNeedModify     = 30_004; // 本科生:用户密码需要更改
 | 
				
			||||
    public static final int UndergradBannedInExclusiveTime  = 30_005; // 本科生:专属选课时间段账号被禁用(--> _ --)
 | 
				
			||||
    public static final int UndergradNeedEvaluate           = 30_006; // 本科生:需要评教
 | 
				
			||||
 | 
				
			||||
    // 研究生
 | 
				
			||||
    public static final int GraduatePasswordWrong   = 40_001; // 研究生:密码错误
 | 
				
			||||
    public static final int GraduateCaptchaWrong    = 40_002; // 研究生:验证码错误
 | 
				
			||||
 | 
				
			||||
    // 图书馆
 | 
				
			||||
    public static final int LibraryUserNotExists        = 50_001; // 图书馆:用户不存在
 | 
				
			||||
    public static final int LibraryUserBanned           = 50_002; // 图书馆:封号
 | 
				
			||||
    public static final int LibraryUserDisabled         = 50_003; // 图书馆:用户账号禁用
 | 
				
			||||
    public static final int LibraryPasswordNeedModify   = 50_004; // 图书馆:用户密码需要更改
 | 
				
			||||
 | 
				
			||||
    // 物理实验
 | 
				
			||||
    public static final int PhysicsPasswordWrong        = 60_001; // 物理实验:用户不存在
 | 
				
			||||
    public static final int PhysicsUserNotCurrentTerm   = 60_002; // 物理实验:用户不在当前学期
 | 
				
			||||
 | 
				
			||||
    private static final Map<Integer, String> text = new HashMap<>(128); | 
				
			||||
 | 
				
			||||
    // 错误码文案
 | 
				
			||||
    static { | 
				
			||||
        text.put(Ok, "ok"); | 
				
			||||
        text.put(ServerInternalError, "服务器内部错误"); | 
				
			||||
        text.put(ApiNotImplement, "接口未实现"); | 
				
			||||
 | 
				
			||||
        // 主模块
 | 
				
			||||
        text.put(UserNotExists, "用户不存在"); | 
				
			||||
 | 
				
			||||
        // 所有模块共用
 | 
				
			||||
        text.put(Unknown, "未知错误"); | 
				
			||||
        text.put(RequestInvalid, "请求无效"); | 
				
			||||
        text.put(CookieInvalid, "提供的cookie无效"); | 
				
			||||
        text.put(NetworkError, "网络错误"); | 
				
			||||
        text.put(RpcError, "上游RPC错误"); | 
				
			||||
        text.put(ParseError, "解析错误"); | 
				
			||||
 | 
				
			||||
        // 本科生
 | 
				
			||||
        text.put(UndergradUserNotExists, "本科生:用户不存在"); | 
				
			||||
        text.put(UndergradUserBanned, "本科生:封号"); | 
				
			||||
        text.put(UndergradUserDisabled, "本科生:用户账号禁用"); | 
				
			||||
        text.put(UndergradPasswordNeedModify, "本科生:用户密码需要更改"); | 
				
			||||
        text.put(UndergradBannedInExclusiveTime, "本科生:专属选课时间段账号被禁用(--> _ --)"); | 
				
			||||
        text.put(UndergradNeedEvaluate, "本科生:需要评教"); | 
				
			||||
 | 
				
			||||
        // 研究生
 | 
				
			||||
        text.put(GraduatePasswordWrong, "研究生:密码错误"); | 
				
			||||
        text.put(GraduateCaptchaWrong, "研究生:验证码错误"); | 
				
			||||
 | 
				
			||||
        // 图书馆
 | 
				
			||||
        text.put(LibraryUserNotExists, "图书馆:用户不存在"); | 
				
			||||
        text.put(LibraryUserBanned, "图书馆:封号"); | 
				
			||||
        text.put(LibraryUserDisabled, "图书馆:用户账号禁用"); | 
				
			||||
        text.put(LibraryPasswordNeedModify, "图书馆:用户密码需要更改"); | 
				
			||||
 | 
				
			||||
        // 物理实验
 | 
				
			||||
        text.put(PhysicsPasswordWrong, "物理实验:用户不存在"); | 
				
			||||
        text.put(PhysicsUserNotCurrentTerm, "物理实验:用户不在当前学期"); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    private final int code; | 
				
			||||
 | 
				
			||||
    private final String description; | 
				
			||||
 | 
				
			||||
    ServiceCode(int code, String description) { | 
				
			||||
        this.code = code; | 
				
			||||
        this.description = description; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    ServiceCode(int code) { | 
				
			||||
        this(code, getDescribe(code)); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public int getCode() { | 
				
			||||
        return code; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public String getDescription() { | 
				
			||||
        return description; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static String getDescribe(int code) { | 
				
			||||
        return text.get(code); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static ServiceCode of(int code) { | 
				
			||||
        return new ServiceCode(code); | 
				
			||||
    } | 
				
			||||
//
 | 
				
			||||
//    public static class Code {
 | 
				
			||||
//        // 所有模块共用
 | 
				
			||||
//        public static final ErrorCode Unknown           = ErrorCode.of(10_000); // 未知错误
 | 
				
			||||
//        public static final ErrorCode RequestInvalid    = ErrorCode.of(10_001); // 请求无效
 | 
				
			||||
//        public static final ErrorCode CookieInvalid     = ErrorCode.of(10_002); // 提供的cookie无效
 | 
				
			||||
//        public static final ErrorCode NetworkError      = ErrorCode.of(10_003); // 网络错误
 | 
				
			||||
//        public static final ErrorCode RpcError          = ErrorCode.of(10_004); // 上游RPC错误
 | 
				
			||||
//        public static final ErrorCode ParseError        = ErrorCode.of(10_005); // 解析错误
 | 
				
			||||
//
 | 
				
			||||
//        // 本科生
 | 
				
			||||
//        public static final ErrorCode UndergradUserNotExists            = ErrorCode.of(20_001); // 本科生:用户不存在
 | 
				
			||||
//        public static final ErrorCode UndergradUserBanned               = ErrorCode.of(20_002); // 本科生:封号
 | 
				
			||||
//        public static final ErrorCode UndergradUserDisabled             = ErrorCode.of(20_003); // 本科生:用户账号禁用
 | 
				
			||||
//        public static final ErrorCode UndergradPasswordNeedModify       = ErrorCode.of(20_004); // 本科生:用户密码需要更改
 | 
				
			||||
//        public static final ErrorCode UndergradBannedInExclusiveTime    = ErrorCode.of(20_005); // 本科生:专属选课时间段账号被禁用(--> _ --)
 | 
				
			||||
//        public static final ErrorCode UndergradNeedEvaluate             = ErrorCode.of(20_006); // 本科生:需要评教
 | 
				
			||||
//
 | 
				
			||||
//        // 研究生
 | 
				
			||||
//        public static final ErrorCode GraduatePasswordWrong = ErrorCode.of(30_001); // 研究生:密码错误
 | 
				
			||||
//        public static final ErrorCode GraduateCaptchaWrong  = ErrorCode.of(30_002); // 研究生:验证码错误
 | 
				
			||||
//
 | 
				
			||||
//        // 图书馆
 | 
				
			||||
//        public static final ErrorCode LibraryUserNotExists      = ErrorCode.of(40_001); // 图书馆:用户不存在
 | 
				
			||||
//        public static final ErrorCode LibraryUserBanned         = ErrorCode.of(40_002); // 图书馆:封号
 | 
				
			||||
//        public static final ErrorCode LibraryUserDisabled       = ErrorCode.of(40_003); // 图书馆:用户账号禁用
 | 
				
			||||
//        public static final ErrorCode LibraryPasswordNeedModify = ErrorCode.of(40_004); // 图书馆:用户密码需要更改
 | 
				
			||||
//
 | 
				
			||||
//        // 物理实验
 | 
				
			||||
//        public static final ErrorCode PhysicsPasswordWrong      = ErrorCode.of(50_001); // 物理实验:用户不存在
 | 
				
			||||
//        public static final ErrorCode PhysicsUserNotCurrentTerm = ErrorCode.of(50_002); // 物理实验:用户不在当前学期
 | 
				
			||||
//    }
 | 
				
			||||
} | 
				
			||||
@ -1,14 +1,13 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.rpc.exception; | 
				
			||||
package wusthelper.internal.rpc.exception; | 
				
			||||
 | 
				
			||||
import java.util.StringJoiner; | 
				
			||||
 | 
				
			||||
public class GraduateRpcException extends RpcException { | 
				
			||||
    public static final int UNDERGRAD_MODULE = 1; | 
				
			||||
 | 
				
			||||
    public GraduateRpcException(TypeCode typeCode, | 
				
			||||
                                SubModuleCode subModuleCode, | 
				
			||||
                                ErrorCode errorCode) { | 
				
			||||
        super(UNDERGRAD_MODULE, | 
				
			||||
        super(GRADUATE_MODULE, | 
				
			||||
                typeCode.ordinal(), | 
				
			||||
                subModuleCode.ordinal() * 100 + errorCode.ordinal(), | 
				
			||||
                new StringJoiner("/") | 
				
			||||
@ -1,9 +1,8 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.rpc.exception; | 
				
			||||
package wusthelper.internal.rpc.exception; | 
				
			||||
 | 
				
			||||
import java.util.StringJoiner; | 
				
			||||
 | 
				
			||||
public class LibraryRpcException extends RpcException { | 
				
			||||
    public static final int LIBRARY_MODULE = 3; | 
				
			||||
 | 
				
			||||
    public LibraryRpcException(TypeCode typeCode, | 
				
			||||
                               SubModuleCode subModuleCode, | 
				
			||||
@ -1,10 +1,8 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.rpc.exception; | 
				
			||||
package wusthelper.internal.rpc.exception; | 
				
			||||
 | 
				
			||||
import java.util.StringJoiner; | 
				
			||||
 | 
				
			||||
public class PhysicsRpcException extends RpcException { | 
				
			||||
    public static final int PHYSICS_MODULE = 4; | 
				
			||||
 | 
				
			||||
    public PhysicsRpcException(TypeCode typeCode, | 
				
			||||
                               SubModuleCode subModuleCode, | 
				
			||||
                               ErrorCode errorCode) { | 
				
			||||
@ -0,0 +1,31 @@ | 
				
			||||
/* | 
				
			||||
 * Class created by lensfrex. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
package wusthelper.internal.rpc.response; | 
				
			||||
 | 
				
			||||
public enum RpcCommonResponseCode { | 
				
			||||
    Success(20000, "成功"), | 
				
			||||
    ParamWrong(30001, "参数错误"), | 
				
			||||
    ServerInternalError(50000, "服务器内部错误"), | 
				
			||||
    ApiNotImplement(0, "接口未实现"), | 
				
			||||
 | 
				
			||||
    ; | 
				
			||||
 | 
				
			||||
    private final int code; | 
				
			||||
 | 
				
			||||
    private final String message; | 
				
			||||
 | 
				
			||||
    RpcCommonResponseCode(int code, String message) { | 
				
			||||
        this.code = code; | 
				
			||||
        this.message = message; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public int getCode() { | 
				
			||||
        return code; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public String getMessage() { | 
				
			||||
        return message; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -1,4 +1,4 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.rpc.util; | 
				
			||||
package wusthelper.internal.rpc.util; | 
				
			||||
 | 
				
			||||
public class EnumUtil { | 
				
			||||
    public static <E extends Enum<E>> boolean equal(int value, Enum<E> e) { | 
				
			||||
@ -0,0 +1,43 @@ | 
				
			||||
package wusthelper.web.exception; | 
				
			||||
 | 
				
			||||
import wusthelper.code.ServiceCode; | 
				
			||||
 | 
				
			||||
public class ServiceException extends RuntimeException { | 
				
			||||
    private final int code; | 
				
			||||
 | 
				
			||||
    public ServiceException(ServiceCode code) { | 
				
			||||
        this(code, code.getDescription()); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public ServiceException(ServiceCode code, String message) { | 
				
			||||
        super(message); | 
				
			||||
        this.code = code.getCode(); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public ServiceException(int code) { | 
				
			||||
        this(code, ServiceCode.getDescribe(code)); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public ServiceException(int code, String message) { | 
				
			||||
        super(message); | 
				
			||||
        this.code = code; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public ServiceCode getCode() { | 
				
			||||
        return ServiceCode.of(code); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public int getCodeValue() { | 
				
			||||
        return code; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * 直接按错误码抛出异常 | 
				
			||||
     * | 
				
			||||
     * @param code 错误码 | 
				
			||||
     * @throws ServiceException . | 
				
			||||
     */ | 
				
			||||
    public static void of(int code) throws ServiceException { | 
				
			||||
        throw new ServiceException(code); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,4 @@ | 
				
			||||
package wusthelper.web.response; | 
				
			||||
 | 
				
			||||
public class V2ErrorCodeConverter { | 
				
			||||
} | 
				
			||||
@ -0,0 +1,73 @@ | 
				
			||||
package wusthelper.web.util; | 
				
			||||
 | 
				
			||||
import cn.hutool.core.util.HexUtil; | 
				
			||||
import cn.hutool.crypto.Mode; | 
				
			||||
import cn.hutool.crypto.Padding; | 
				
			||||
import cn.hutool.crypto.symmetric.AES; | 
				
			||||
import cn.hutool.crypto.symmetric.SymmetricCrypto; | 
				
			||||
 | 
				
			||||
import java.nio.charset.StandardCharsets; | 
				
			||||
import java.util.StringJoiner; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * 密码编解码器, | 
				
			||||
 * 用aes加密而不是常规密码存储使用的hash摘要,是因为有获取明文密码的需求,毕竟登录进系统还是要明文密码的, | 
				
			||||
 * 日后如果将数据获取转到客户端上进行,可以改为bcrypt存储 | 
				
			||||
 */ | 
				
			||||
public class PasswordCodec { | 
				
			||||
 | 
				
			||||
    private final SymmetricCrypto aes; | 
				
			||||
 | 
				
			||||
    public PasswordCodec(String key) { | 
				
			||||
        byte[] keyBytes = normalization(key); | 
				
			||||
        this.aes = new AES(Mode.ECB, Padding.PKCS5Padding, keyBytes); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public PasswordCodec(byte[] key) { | 
				
			||||
        this.aes = new AES(Mode.ECB, Padding.PKCS5Padding, key); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    private static byte[] normalization(String key) { | 
				
			||||
        if (key.length() < 16) { | 
				
			||||
            StringJoiner sj = new StringJoiner(key); | 
				
			||||
            for (int i = 0; i < 16 - key.length(); i++) { | 
				
			||||
                sj.add("a"); | 
				
			||||
            } | 
				
			||||
            key = sj.toString(); | 
				
			||||
        } else if (key.length() > 16) { | 
				
			||||
            key = key.substring(15); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return key.getBytes(StandardCharsets.UTF_8); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public String encode(String raw) { | 
				
			||||
        if (raw == null) { | 
				
			||||
            return null; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        byte[] data = aes.encrypt(raw.getBytes(StandardCharsets.UTF_8)); | 
				
			||||
        return HexUtil.encodeHexStr(data); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public String decode(String encodedHex) { | 
				
			||||
        if (encodedHex == null) { | 
				
			||||
            return null; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        byte[] data = aes.decrypt(HexUtil.decodeHex(encodedHex)); | 
				
			||||
        return new String(data); | 
				
			||||
    } | 
				
			||||
//
 | 
				
			||||
//    public static PasswordUtil getInstance(String key) {
 | 
				
			||||
//        if (instance == null) {
 | 
				
			||||
//            synchronized (PasswordUtil.class) {
 | 
				
			||||
//                if (instance == null) {
 | 
				
			||||
//                    instance = new PasswordUtil(key);
 | 
				
			||||
//                }
 | 
				
			||||
//            }
 | 
				
			||||
//        }
 | 
				
			||||
//
 | 
				
			||||
//        return instance;
 | 
				
			||||
//    }
 | 
				
			||||
} | 
				
			||||
@ -1 +1 @@ | 
				
			||||
Subproject commit 736dc78d1b9e64124474cee98c5db6e8212fa096 | 
				
			||||
Subproject commit 367ddbb930b50cadbb56bd97acee05d721b9427b | 
				
			||||
@ -1,13 +1,13 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.rpc; | 
				
			||||
package wusthelper.internal.rpc; | 
				
			||||
 | 
				
			||||
import cn.hutool.core.thread.ThreadUtil; | 
				
			||||
import cn.hutool.core.util.RandomUtil; | 
				
			||||
import cn.wustlinghang.mywust.network.Requester; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.client.ConsulClient; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.client.FrpcClient; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.config.FrpConfig; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.config.RegisterConfig; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.entity.RegisterRequestBody; | 
				
			||||
import wusthelper.internal.rpc.client.ConsulClient; | 
				
			||||
import wusthelper.internal.rpc.client.FrpcClient; | 
				
			||||
import wusthelper.internal.rpc.config.FrpConfig; | 
				
			||||
import wusthelper.internal.rpc.config.RegisterConfig; | 
				
			||||
import wusthelper.internal.rpc.entity.RegisterRequestBody; | 
				
			||||
import com.fasterxml.jackson.databind.JsonNode; | 
				
			||||
import com.fasterxml.jackson.databind.ObjectMapper; | 
				
			||||
import lombok.extern.slf4j.Slf4j; | 
				
			||||
@ -1,10 +1,10 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.rpc.client; | 
				
			||||
package wusthelper.internal.rpc.client; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.network.Requester; | 
				
			||||
import cn.wustlinghang.mywust.network.entitys.HttpResponse; | 
				
			||||
import cn.wustlinghang.mywust.network.request.RequestFactory; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.config.RegisterConfig; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.entity.RegisterRequestBody; | 
				
			||||
import wusthelper.internal.rpc.config.RegisterConfig; | 
				
			||||
import wusthelper.internal.rpc.entity.RegisterRequestBody; | 
				
			||||
import com.fasterxml.jackson.databind.ObjectMapper; | 
				
			||||
import com.google.common.collect.Lists; | 
				
			||||
import lombok.extern.slf4j.Slf4j; | 
				
			||||
@ -1,10 +1,10 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.rpc.client; | 
				
			||||
package wusthelper.internal.rpc.client; | 
				
			||||
 | 
				
			||||
import cn.hutool.core.codec.Base64; | 
				
			||||
import cn.wustlinghang.mywust.network.entitys.HttpResponse; | 
				
			||||
import cn.wustlinghang.mywust.network.request.RequestFactory; | 
				
			||||
import cn.wustlinghang.mywust.network.Requester; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.config.FrpConfig; | 
				
			||||
import wusthelper.internal.rpc.config.FrpConfig; | 
				
			||||
import com.fasterxml.jackson.databind.JsonNode; | 
				
			||||
import com.fasterxml.jackson.databind.ObjectMapper; | 
				
			||||
import com.fasterxml.jackson.databind.node.MissingNode; | 
				
			||||
@ -1,4 +1,4 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.rpc.config; | 
				
			||||
package wusthelper.internal.rpc.config; | 
				
			||||
 | 
				
			||||
import lombok.Builder; | 
				
			||||
import lombok.Data; | 
				
			||||
@ -1,4 +1,4 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.rpc.config; | 
				
			||||
package wusthelper.internal.rpc.config; | 
				
			||||
 | 
				
			||||
import lombok.Builder; | 
				
			||||
import lombok.Data; | 
				
			||||
@ -1,4 +1,4 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.rpc.entity; | 
				
			||||
package wusthelper.internal.rpc.entity; | 
				
			||||
 | 
				
			||||
import lombok.Builder; | 
				
			||||
 | 
				
			||||
@ -1,10 +1,9 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.graduate; | 
				
			||||
package wusthelper.internal.graduate; | 
				
			||||
 | 
				
			||||
import io.quarkus.runtime.Startup; | 
				
			||||
import jakarta.annotation.PostConstruct; | 
				
			||||
import jakarta.inject.Singleton; | 
				
			||||
import lombok.extern.slf4j.Slf4j; | 
				
			||||
import org.eclipse.microprofile.config.inject.ConfigProperties; | 
				
			||||
import org.eclipse.microprofile.config.inject.ConfigProperty; | 
				
			||||
 | 
				
			||||
@Slf4j | 
				
			||||
@ -1,7 +1,7 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.physics.api.http.v1; | 
				
			||||
package wusthelper.internal.graduate.api.http.v1; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.wusthelper.internal.physics.services.LoginService; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import wusthelper.internal.graduate.services.LoginService; | 
				
			||||
import wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import jakarta.validation.constraints.NotNull; | 
				
			||||
import jakarta.ws.rs.GET; | 
				
			||||
import jakarta.ws.rs.Path; | 
				
			||||
@ -1,8 +1,8 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.graduate.api.http.v1; | 
				
			||||
package wusthelper.internal.graduate.api.http.v1; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.data.global.Course; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.graduate.services.CourseTableService; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import wusthelper.internal.graduate.services.CourseTableService; | 
				
			||||
import wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import jakarta.enterprise.context.ApplicationScoped; | 
				
			||||
import jakarta.validation.constraints.NotNull; | 
				
			||||
import jakarta.ws.rs.GET; | 
				
			||||
@ -1,8 +1,8 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.graduate.api.http.v1; | 
				
			||||
package wusthelper.internal.graduate.api.http.v1; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.data.global.Score; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.graduate.services.ScoreService; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import wusthelper.internal.graduate.services.ScoreService; | 
				
			||||
import wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import jakarta.enterprise.context.ApplicationScoped; | 
				
			||||
import jakarta.validation.constraints.NotNull; | 
				
			||||
import jakarta.ws.rs.GET; | 
				
			||||
@ -1,8 +1,8 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.undergrad.api.http.v1; | 
				
			||||
package wusthelper.internal.graduate.api.http.v1; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.data.global.StudentInfo; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.undergrad.services.StudentInfoService; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import wusthelper.internal.graduate.services.StudentInfoService; | 
				
			||||
import wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import jakarta.enterprise.context.ApplicationScoped; | 
				
			||||
import jakarta.validation.constraints.NotNull; | 
				
			||||
import jakarta.ws.rs.GET; | 
				
			||||
@ -1,7 +1,7 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.graduate.api.http.v1; | 
				
			||||
package wusthelper.internal.graduate.api.http.v1; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.wusthelper.internal.graduate.services.TrainingPlanService; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import wusthelper.internal.graduate.services.TrainingPlanService; | 
				
			||||
import wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import jakarta.enterprise.context.ApplicationScoped; | 
				
			||||
import jakarta.validation.constraints.NotNull; | 
				
			||||
import jakarta.ws.rs.GET; | 
				
			||||
@ -1,6 +1,6 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.physics.api.http.v1.handler; | 
				
			||||
package wusthelper.internal.graduate.api.http.v1.handler; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import jakarta.ws.rs.core.Response; | 
				
			||||
import jakarta.ws.rs.ext.ExceptionMapper; | 
				
			||||
import jakarta.ws.rs.ext.Provider; | 
				
			||||
@ -1,7 +1,7 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.physics.api.http.v1.interceptor; | 
				
			||||
package wusthelper.internal.graduate.api.http.v1.interceptor; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.wusthelper.internal.physics.api.http.v1.handler.BaseExceptionHandler; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.response.RpcResponseDto; | 
				
			||||
import wusthelper.internal.graduate.api.http.v1.handler.BaseExceptionHandler; | 
				
			||||
import wusthelper.internal.rpc.response.RpcResponseDto; | 
				
			||||
import com.fasterxml.jackson.databind.ObjectMapper; | 
				
			||||
import jakarta.ws.rs.WebApplicationException; | 
				
			||||
import jakarta.ws.rs.core.HttpHeaders; | 
				
			||||
@ -1,8 +1,7 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.physics.bean; | 
				
			||||
package wusthelper.internal.graduate.bean; | 
				
			||||
 | 
				
			||||
import com.fasterxml.jackson.databind.ObjectMapper; | 
				
			||||
import jakarta.enterprise.context.ApplicationScoped; | 
				
			||||
import jakarta.inject.Singleton; | 
				
			||||
 | 
				
			||||
public class JacksonBean { | 
				
			||||
    @ApplicationScoped | 
				
			||||
@ -1,4 +1,4 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.graduate.bean; | 
				
			||||
package wusthelper.internal.graduate.bean; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.core.parser.graduate.GraduateCourseTableParser; | 
				
			||||
import cn.wustlinghang.mywust.core.parser.graduate.GraduateScoreParser; | 
				
			||||
@ -1,4 +1,4 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.graduate.bean; | 
				
			||||
package wusthelper.internal.graduate.bean; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.core.request.service.auth.GraduateLogin; | 
				
			||||
import cn.wustlinghang.mywust.core.request.service.captcha.solver.DdddOcrCaptchaSolver; | 
				
			||||
@ -1,10 +1,10 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.physics.rpc; | 
				
			||||
package wusthelper.internal.graduate.rpc; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.network.Requester; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.physics.rpc.config.RpcConfig; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.FrpConsulRegister; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.config.FrpConfig; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.config.RegisterConfig; | 
				
			||||
import wusthelper.internal.graduate.rpc.config.RpcConfig; | 
				
			||||
import wusthelper.internal.rpc.FrpConsulRegister; | 
				
			||||
import wusthelper.internal.rpc.config.FrpConfig; | 
				
			||||
import wusthelper.internal.rpc.config.RegisterConfig; | 
				
			||||
import com.fasterxml.jackson.databind.ObjectMapper; | 
				
			||||
import io.quarkus.runtime.Startup; | 
				
			||||
import jakarta.annotation.PostConstruct; | 
				
			||||
@ -1,4 +1,4 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.physics.rpc.config; | 
				
			||||
package wusthelper.internal.graduate.rpc.config; | 
				
			||||
 | 
				
			||||
import jakarta.inject.Singleton; | 
				
			||||
import jakarta.ws.rs.DefaultValue; | 
				
			||||
@ -1,4 +1,4 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.physics.rpc.health; | 
				
			||||
package wusthelper.internal.graduate.rpc.health; | 
				
			||||
 | 
				
			||||
import jakarta.ws.rs.GET; | 
				
			||||
import jakarta.ws.rs.Path; | 
				
			||||
@ -1,7 +1,7 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.graduate.services; | 
				
			||||
package wusthelper.internal.graduate.services; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.exception.ApiException; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.GraduateRpcException; | 
				
			||||
import wusthelper.internal.rpc.exception.GraduateRpcException; | 
				
			||||
import lombok.extern.slf4j.Slf4j; | 
				
			||||
 | 
				
			||||
@Slf4j | 
				
			||||
@ -1,12 +1,12 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.graduate.services; | 
				
			||||
package wusthelper.internal.graduate.services; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.core.parser.graduate.GraduateCourseTableParser; | 
				
			||||
import cn.wustlinghang.mywust.core.request.service.graduate.GraduateCourseTableApiService; | 
				
			||||
import cn.wustlinghang.mywust.data.global.Course; | 
				
			||||
import cn.wustlinghang.mywust.exception.ApiException; | 
				
			||||
import cn.wustlinghang.mywust.network.RequestClientOption; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.GraduateRpcException; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import wusthelper.internal.rpc.exception.GraduateRpcException; | 
				
			||||
import wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import jakarta.enterprise.context.ApplicationScoped; | 
				
			||||
 | 
				
			||||
import java.io.IOException; | 
				
			||||
@ -1,9 +1,9 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.graduate.services; | 
				
			||||
package wusthelper.internal.graduate.services; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.core.request.service.auth.GraduateLogin; | 
				
			||||
import cn.wustlinghang.mywust.exception.ApiException; | 
				
			||||
import cn.wustlinghang.mywust.network.RequestClientOption; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.GraduateRpcException; | 
				
			||||
import wusthelper.internal.rpc.exception.GraduateRpcException; | 
				
			||||
import jakarta.enterprise.context.ApplicationScoped; | 
				
			||||
import lombok.extern.slf4j.Slf4j; | 
				
			||||
import org.eclipse.microprofile.config.inject.ConfigProperty; | 
				
			||||
@ -1,12 +1,12 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.graduate.services; | 
				
			||||
package wusthelper.internal.graduate.services; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.core.parser.graduate.GraduateScoreParser; | 
				
			||||
import cn.wustlinghang.mywust.core.request.service.graduate.GraduateScoreApiService; | 
				
			||||
import cn.wustlinghang.mywust.data.global.Score; | 
				
			||||
import cn.wustlinghang.mywust.exception.ApiException; | 
				
			||||
import cn.wustlinghang.mywust.network.RequestClientOption; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.GraduateRpcException; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import wusthelper.internal.rpc.exception.GraduateRpcException; | 
				
			||||
import wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import jakarta.enterprise.context.ApplicationScoped; | 
				
			||||
 | 
				
			||||
import java.io.IOException; | 
				
			||||
@ -1,12 +1,12 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.graduate.services; | 
				
			||||
package wusthelper.internal.graduate.services; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.core.parser.graduate.GraduateStudentInfoPageParser; | 
				
			||||
import cn.wustlinghang.mywust.core.request.service.graduate.GraduateStudentInfoApiService; | 
				
			||||
import cn.wustlinghang.mywust.data.global.StudentInfo; | 
				
			||||
import cn.wustlinghang.mywust.exception.ApiException; | 
				
			||||
import cn.wustlinghang.mywust.network.RequestClientOption; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.GraduateRpcException; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import wusthelper.internal.rpc.exception.GraduateRpcException; | 
				
			||||
import wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import jakarta.enterprise.context.ApplicationScoped; | 
				
			||||
 | 
				
			||||
import java.io.IOException; | 
				
			||||
@ -1,11 +1,11 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.graduate.services; | 
				
			||||
package wusthelper.internal.graduate.services; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.core.parser.graduate.GraduateTrainingPlanPageParser; | 
				
			||||
import cn.wustlinghang.mywust.core.request.service.graduate.GraduateTrainingPlanApiService; | 
				
			||||
import cn.wustlinghang.mywust.exception.ApiException; | 
				
			||||
import cn.wustlinghang.mywust.network.RequestClientOption; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.GraduateRpcException; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import wusthelper.internal.rpc.exception.GraduateRpcException; | 
				
			||||
import wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import jakarta.enterprise.context.ApplicationScoped; | 
				
			||||
 | 
				
			||||
import java.io.IOException; | 
				
			||||
@ -1,4 +1,4 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.library; | 
				
			||||
package wusthelper.internal.library; | 
				
			||||
 | 
				
			||||
import io.quarkus.runtime.Startup; | 
				
			||||
import jakarta.annotation.PostConstruct; | 
				
			||||
@ -1,7 +1,7 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.library.api.http.v1; | 
				
			||||
package wusthelper.internal.library.api.http.v1; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.wusthelper.internal.library.services.BookCoverImageUrlService; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import wusthelper.internal.library.services.BookCoverImageUrlService; | 
				
			||||
import wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import jakarta.enterprise.context.ApplicationScoped; | 
				
			||||
import jakarta.validation.constraints.NotNull; | 
				
			||||
import jakarta.ws.rs.GET; | 
				
			||||
@ -1,8 +1,8 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.library.api.http.v1; | 
				
			||||
package wusthelper.internal.library.api.http.v1; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.data.library.parsed.BookDetail; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.library.services.BookDetailService; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import wusthelper.internal.library.services.BookDetailService; | 
				
			||||
import wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import jakarta.enterprise.context.ApplicationScoped; | 
				
			||||
import jakarta.validation.constraints.NotNull; | 
				
			||||
import jakarta.ws.rs.GET; | 
				
			||||
@ -1,8 +1,8 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.library.api.http.v1; | 
				
			||||
package wusthelper.internal.library.api.http.v1; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.data.library.parsed.BookHolding; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.library.services.BookHoldingService; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import wusthelper.internal.library.services.BookHoldingService; | 
				
			||||
import wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import jakarta.enterprise.context.ApplicationScoped; | 
				
			||||
import jakarta.validation.constraints.NotNull; | 
				
			||||
import jakarta.ws.rs.GET; | 
				
			||||
@ -1,7 +1,7 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.library.api.http.v1; | 
				
			||||
package wusthelper.internal.library.api.http.v1; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.wusthelper.internal.library.services.LoginService; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import wusthelper.internal.library.services.LoginService; | 
				
			||||
import wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import jakarta.validation.constraints.NotNull; | 
				
			||||
import jakarta.ws.rs.GET; | 
				
			||||
import jakarta.ws.rs.Path; | 
				
			||||
@ -1,9 +1,9 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.library.api.http.v1; | 
				
			||||
package wusthelper.internal.library.api.http.v1; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.data.library.PagingResult; | 
				
			||||
import cn.wustlinghang.mywust.data.library.origin.CurrentLoanBook; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.library.services.CurrentLoanService; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import wusthelper.internal.library.services.CurrentLoanService; | 
				
			||||
import wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import jakarta.enterprise.context.ApplicationScoped; | 
				
			||||
import jakarta.validation.constraints.NotNull; | 
				
			||||
import jakarta.ws.rs.DefaultValue; | 
				
			||||
@ -1,9 +1,9 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.library.api.http.v1; | 
				
			||||
package wusthelper.internal.library.api.http.v1; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.data.library.PagingResult; | 
				
			||||
import cn.wustlinghang.mywust.data.library.origin.HistoryLoanBook; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.library.services.LoanHistoryService; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import wusthelper.internal.library.services.LoanHistoryService; | 
				
			||||
import wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import jakarta.enterprise.context.ApplicationScoped; | 
				
			||||
import jakarta.validation.constraints.NotNull; | 
				
			||||
import jakarta.ws.rs.DefaultValue; | 
				
			||||
@ -1,9 +1,9 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.library.api.http.v1; | 
				
			||||
package wusthelper.internal.library.api.http.v1; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.data.library.PagingResult; | 
				
			||||
import cn.wustlinghang.mywust.data.library.origin.BaseLoanBook; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.library.services.OverdueSoonService; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import wusthelper.internal.library.services.OverdueSoonService; | 
				
			||||
import wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import jakarta.enterprise.context.ApplicationScoped; | 
				
			||||
import jakarta.validation.constraints.NotNull; | 
				
			||||
import jakarta.ws.rs.DefaultValue; | 
				
			||||
@ -1,9 +1,9 @@ | 
				
			||||
package cn.wustlinghang.wusthelper.internal.library.api.http.v1; | 
				
			||||
package wusthelper.internal.library.api.http.v1; | 
				
			||||
 | 
				
			||||
import cn.wustlinghang.mywust.data.library.PagingResult; | 
				
			||||
import cn.wustlinghang.mywust.data.library.origin.BookSearchResult; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.library.services.SearchService; | 
				
			||||
import cn.wustlinghang.wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import wusthelper.internal.library.services.SearchService; | 
				
			||||
import wusthelper.internal.rpc.exception.RpcException; | 
				
			||||
import jakarta.enterprise.context.ApplicationScoped; | 
				
			||||
import jakarta.validation.constraints.NotNull; | 
				
			||||
import jakarta.ws.rs.DefaultValue; | 
				
			||||
Some files were not shown because too many files have changed in this diff Show More
					Loading…
					
					
				
		Reference in new issue