feat: add verify code generator

This commit is contained in:
wzp 2024-12-24 11:51:25 +08:00
parent 057a5aab9b
commit fb32577bff
16 changed files with 112 additions and 28 deletions

View File

@ -4,7 +4,7 @@ import lombok.RequiredArgsConstructor;
import org.blue.club.annotation.Auth;
import org.blue.club.dao.UserDao;
import org.blue.club.entities.dto.User;
import org.blue.club.entities.vo.UserVo;
import org.blue.club.entities.vo.data.UserVo;
import org.mmga.spring.boot.starter.componet.AuthorizationHandler;
import org.mmga.spring.boot.starter.componet.JwtUtils;
import org.mmga.spring.boot.starter.entities.Result;

View File

@ -10,6 +10,7 @@ import lombok.extern.slf4j.Slf4j;
import org.blue.club.annotation.Auth;
import org.blue.club.entities.dto.User;
import org.blue.club.entities.dto.req.*;
import org.blue.club.entities.dto.resp.VerifyCodeResponse;
import org.blue.club.services.UserServices;
import org.mmga.spring.boot.starter.annotation.AuthMapping;
import org.mmga.spring.boot.starter.entities.PagerData;
@ -87,7 +88,7 @@ public class UserController {
@GetMapping("/verify")
@Operation(description = "获取验证码")
public Result<VerifyResponseVo> generatorVerifyCode() {
public Result<VerifyCodeResponse> generatorVerifyCode() {
return userServices.getVerifyCode();
}

View File

@ -2,7 +2,7 @@ package org.blue.club.dao;
import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.blue.club.entities.vo.UserVo;
import org.blue.club.entities.vo.data.UserVo;
@Mapper
public interface UserDao extends BaseMapper<UserVo> {

View File

@ -1,6 +1,6 @@
package org.blue.club.dao.redis;
import org.blue.club.entities.vo.AvatarTmpVo;
import org.blue.club.entities.vo.data.AvatarTmpVo;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

View File

@ -4,8 +4,8 @@ import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.RelationManyToOne;
import jakarta.annotation.Nullable;
import lombok.Data;
import org.blue.club.entities.vo.AuthVo;
import org.blue.club.entities.vo.ClubVo;
import org.blue.club.entities.vo.data.AuthVo;
import org.blue.club.entities.vo.data.ClubVo;
import org.mmga.spring.boot.starter.interfaces.IdHolder;
@Data

View File

@ -0,0 +1,8 @@
package org.blue.club.entities.dto.resp;
import io.swagger.v3.oas.annotations.media.Schema;
@Schema(description = "验证码返回值")
public record VerifyCodeResponse(@Schema(description = "验证码图像base64") String img,
@Schema(description = "验证码验证密钥") String key) {
}

View File

@ -1,4 +1,4 @@
package org.blue.club.entities.vo;
package org.blue.club.entities.vo.data;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Table;
@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
@Table("auth_permission")
public class AuthPermissionVo extends BaseVo {
public class AuthPermissionVo extends BaseDataVo {
@Column("auth_id")
private Long authId;
@Column("permission_id")

View File

@ -1,4 +1,4 @@
package org.blue.club.entities.vo;
package org.blue.club.entities.vo.data;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.RelationManyToMany;
@ -11,7 +11,7 @@ import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Table("auth")
@Data
public class AuthVo extends BaseVo {
public class AuthVo extends BaseDataVo {
@Id
private Long id;
private String name;

View File

@ -1,4 +1,4 @@
package org.blue.club.entities.vo;
package org.blue.club.entities.vo.data;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;

View File

@ -1,10 +1,10 @@
package org.blue.club.entities.vo;
package org.blue.club.entities.vo.data;
import com.mybatisflex.annotation.Column;
import java.util.Date;
public class BaseVo {
public class BaseDataVo {
@Column(value = "create_time", onUpdateValue = "now()", onInsertValue = "now()")
protected Date createTime;
@Column(value = "update_time", onUpdateValue = "now()", onInsertValue = "now()")

View File

@ -1,4 +1,4 @@
package org.blue.club.entities.vo;
package org.blue.club.entities.vo.data;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Table;
@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Table("club_user_auth")
@Data
public class ClubUserAuthVo extends BaseVo {
public class ClubUserAuthVo extends BaseDataVo {
@Column("user_id")
private Long userId;
@Column("club_id")

View File

@ -1,4 +1,4 @@
package org.blue.club.entities.vo;
package org.blue.club.entities.vo.data;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.Table;
@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
@Table("club")
public class ClubVo extends BaseVo {
public class ClubVo extends BaseDataVo {
@Id
private Long id;
private String name;

View File

@ -1,4 +1,4 @@
package org.blue.club.entities.vo;
package org.blue.club.entities.vo.data;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.Table;
@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Table("permission")
@Data
public class PermissionVo extends BaseVo {
public class PermissionVo extends BaseDataVo {
@Id
private Long id;
private String name;

View File

@ -1,4 +1,4 @@
package org.blue.club.entities.vo;
package org.blue.club.entities.vo.data;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.RelationManyToOne;
@ -11,7 +11,7 @@ import org.mmga.spring.boot.starter.annotation.VoIgnore;
@EqualsAndHashCode(callSuper = true)
@Data
@Table("user")
public class UserVo extends BaseVo {
public class UserVo extends BaseDataVo {
@Id
private Long id;
private String name;

View File

@ -11,8 +11,9 @@ import org.blue.club.dao.redis.AvatarOperationDao;
import org.blue.club.dao.redis.VerifyDao;
import org.blue.club.entities.dto.User;
import org.blue.club.entities.dto.req.*;
import org.blue.club.entities.vo.AvatarTmpVo;
import org.blue.club.entities.vo.UserVo;
import org.blue.club.entities.dto.resp.VerifyCodeResponse;
import org.blue.club.entities.vo.data.AvatarTmpVo;
import org.blue.club.entities.vo.data.UserVo;
import org.blue.club.entities.vo.VerifyVo;
import org.blue.club.utils.FileUtils;
import org.mmga.spring.boot.starter.entities.PagerData;
@ -154,14 +155,30 @@ public class UserServices {
if (byId.isEmpty()) return Result.failed(HttpStatus.NOT_FOUND, "操作码错误或过期");
AvatarTmpVo avatarTmpVo = byId.get();
File tmpFile = new File(tmpFolder, avatarOperationCode);
File targetFile = new File(avatarFolder, avatarTmpVo.sha1());
String sha1 = avatarTmpVo.sha1();
File targetFile = new File(avatarFolder, sha1);
Optional<Result<Boolean>> booleanResult = changeAvatarFile(tmpFile, targetFile);
if (booleanResult.isPresent()) return booleanResult.get();
avatarOperationDao.deleteById(avatarOperationCode);
UserVo userVo = new UserVo();
userVo.setId(user.getId());
userVo.setAvatar(user.getAvatar());
userDao.update(userVo);
return Result.success(true);
}
public Optional<Result<Boolean>> changeAvatarFile(File tmpFile, File targetFile) {
if (targetFile.exists()) {
fileUtils.tryDeleteOrDeleteOnExit(targetFile);
return Result.success(true);
return Optional.empty();
}
if (!tmpFile.renameTo(targetFile))
return Result.failed(HttpStatus.INTERNAL_SERVER_ERROR, "移动头像文件失败!请联系管理员处理");
// TODO 修改用户头像hash
return Result.success();
return Optional.of(Result.failed(HttpStatus.INTERNAL_SERVER_ERROR, "移动头像文件失败!请联系管理员处理"));
return Optional.empty();
}
public Result<VerifyCodeResponse> getVerifyCode() {
return null;
}
}

View File

@ -0,0 +1,58 @@
package org.blue.club.utils;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.apache.commons.codec.binary.Base64OutputStream;
import org.blue.club.dao.redis.VerifyDao;
import org.blue.club.entities.dto.resp.VerifyCodeResponse;
import org.blue.club.entities.vo.VerifyVo;
import org.mmga.spring.boot.starter.utils.RandomUtils;
import org.springframework.stereotype.Component;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Random;
@Component
@RequiredArgsConstructor
public class VerifyCodeUtils {
public static final int width = 120;
public static final int height = 40;
public static final int fontSize = 25;
public static final Font mainFont = new Font("宋体", Font.BOLD, fontSize);
private final RandomUtils randomUtils;
private final VerifyDao verifyDao;
@SneakyThrows
public VerifyCodeResponse generateVerifyCode() {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics g = image.createGraphics();
g.setFont(mainFont);
String text = randomUtils.generatorRandomFileName(4);
int x = 0;
for (char c : text.toCharArray()) {
Random random = new Random();
g.setColor(new Color(20 + random.nextInt(120), 20 + random.nextInt(120), 20 + random.nextInt(120)));
g.drawString(c + "", 15 + x * 20, 20 + new Random().nextInt(10));
for (int j = 0; j < random.nextInt(1, 5); j++) {
g.drawLine(random.nextInt(width), random.nextInt(height), random.nextInt(width), random.nextInt(height));
}
x++;
}
g.dispose();
String s = randomUtils.generatorRandomString(32);
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); Base64OutputStream base64OutputStream = new Base64OutputStream(byteArrayOutputStream)) {
ImageIO.write(image, "png", base64OutputStream);
base64OutputStream.flush();
String base64 = byteArrayOutputStream.toString(StandardCharsets.UTF_8);
verifyDao.save(new VerifyVo(s, text, new Date()));
return new VerifyCodeResponse(base64, s);
}
}
}