Merge branch 'dev' into main

main
ZhouXY108 2023-01-28 17:37:12 +08:00
commit 1611bf38e8
22 changed files with 250 additions and 243 deletions

2
.gitignore vendored
View File

@ -32,6 +32,8 @@ build/
### VS Code ### ### VS Code ###
.vscode/ .vscode/
log/
### bak ### ### bak ###
*.bak *.bak
*-secret.yaml

View File

@ -1,18 +0,0 @@
package xyz.zhouxy.plusone.exception.config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import xyz.zhouxy.plusone.constant.ErrorCodeConsts;
import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler.ExceptionInfoHolder;
@Configuration
public class PlusoneExceptionHandlerConfig {
@Bean
@ConditionalOnMissingBean
ExceptionInfoHolder exceptionInfoHolder() {
return new ExceptionInfoHolder(ErrorCodeConsts.DEFAULT_ERROR_CODE);
}
}

View File

@ -4,8 +4,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler.ExceptionInfoHolder;
/** /**
* AllExceptionHandlerConfig * AllExceptionHandlerConfig
*/ */
@ -14,7 +12,7 @@ import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler.ExceptionInfoHo
public class AllExceptionHandlerConfig { public class AllExceptionHandlerConfig {
@Bean @Bean
AllExceptionHandler getAllExceptionHandler(ExceptionInfoHolder exceptionInfoHolder) { AllExceptionHandler getAllExceptionHandler() {
return new AllExceptionHandler(exceptionInfoHolder); return new AllExceptionHandler(ExceptionInfoHolderFactory.newDefaultExceptionInfoHolder());
} }
} }

View File

@ -41,13 +41,13 @@ import xyz.zhouxy.plusone.util.RestfulResult;
@Slf4j @Slf4j
public class DefaultExceptionHandler extends BaseExceptionHandler { public class DefaultExceptionHandler extends BaseExceptionHandler {
public DefaultExceptionHandler(ExceptionInfoHolder exceptionInfoHolder) { public DefaultExceptionHandler() {
super(exceptionInfoHolder); super(ExceptionInfoHolderFactory.newDefaultExceptionInfoHolder());
set(IllegalArgumentException.class, 4010000, "格式错误", HttpStatus.FORBIDDEN); set(IllegalArgumentException.class, 4010000, "格式错误", HttpStatus.FORBIDDEN);
set(DataAccessException.class, 6030000, "数据库错误", HttpStatus.INTERNAL_SERVER_ERROR, true); set(DataAccessException.class, 6030000, "数据库错误", HttpStatus.INTERNAL_SERVER_ERROR, true);
set(MethodArgumentNotValidException.class, set(MethodArgumentNotValidException.class,
4040401, 4040401,
e -> ((MethodArgumentNotValidException) e).getAllErrors() e -> e.getAllErrors()
.stream() .stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage) .map(DefaultMessageSourceResolvable::getDefaultMessage)
.toList() .toList()

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<artifactId>plusone-basic</artifactId> <artifactId>plusone-basic</artifactId>
@ -39,12 +39,12 @@
<dependency> <dependency>
<groupId>xyz.zhouxy.plusone</groupId> <groupId>xyz.zhouxy.plusone</groupId>
<artifactId>plusone-validator</artifactId> <artifactId>plusone-validator</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.1.0-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>xyz.zhouxy.plusone</groupId> <groupId>xyz.zhouxy.plusone</groupId>
<artifactId>plusone-exception-handler</artifactId> <artifactId>plusone-exception-handler</artifactId>
<version>0.0.5-SNAPSHOT</version> <version>0.0.6-SNAPSHOT</version>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -0,0 +1,15 @@
package xyz.zhouxy.plusone.exception.handler;
import xyz.zhouxy.plusone.constant.ErrorCodeConsts;
import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler.ExceptionInfoHolder;
public class ExceptionInfoHolderFactory {
private ExceptionInfoHolderFactory() {
throw new IllegalStateException("Utility class");
}
public static ExceptionInfoHolder newDefaultExceptionInfoHolder() {
return new ExceptionInfoHolder(ErrorCodeConsts.DEFAULT_ERROR_CODE);
}
}

View File

@ -1,34 +0,0 @@
package xyz.zhouxy.plusone.sql;
import java.util.Objects;
import org.apache.ibatis.jdbc.AbstractSQL;
/**
* MyBatis SQL
*
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
*/
public class SQL extends AbstractSQL<SQL> {
public SQL SET_IF(boolean condition, String sets) {
return condition ? SET(sets) : getSelf();
}
public SQL SET_IF_NOT_NULL(Object param, String sets) {
return Objects.nonNull(param) ? SET(sets) : getSelf();
}
public SQL WHERE_IF(boolean condition, String sqlCondition) {
return condition ? WHERE(sqlCondition) : getSelf();
}
public SQL WHERE_IF_NOT_NULL(Object param, String sqlCondition) {
return Objects.nonNull(param) ? WHERE(sqlCondition) : getSelf();
}
@Override
public SQL getSelf() {
return this;
}
}

View File

@ -2,14 +2,14 @@ package xyz.zhouxy.plusone.validator;
import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.bind.annotation.RestControllerAdvice;
import xyz.zhouxy.plusone.constant.ErrorCodeConsts;
import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler; import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler;
import xyz.zhouxy.plusone.exception.handler.ExceptionInfoHolderFactory;
@RestControllerAdvice @RestControllerAdvice
public class InvalidInputExceptionHandler extends BaseExceptionHandler { public class InvalidInputExceptionHandler extends BaseExceptionHandler {
protected InvalidInputExceptionHandler() { protected InvalidInputExceptionHandler() {
super(new ExceptionInfoHolder(ErrorCodeConsts.DEFAULT_ERROR_CODE)); super(ExceptionInfoHolderFactory.newDefaultExceptionInfoHolder());
set(InvalidInputException.class, InvalidInputException.ERROR_CODE, "无效的用户输入"); set(InvalidInputException.class, InvalidInputException.ERROR_CODE, "无效的用户输入");
} }
} }

View File

@ -6,7 +6,7 @@ import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import xyz.zhouxy.plusone.constant.RegexConsts; import xyz.zhouxy.plusone.constant.RegexConsts;
import xyz.zhouxy.plusone.validator.validator2.BaseValidator2; import xyz.zhouxy.plusone.validator.BaseValidator;
class BaseValidator2Test { class BaseValidator2Test {
@ -27,15 +27,16 @@ class LoginCommand {
private boolean rememberMe; private boolean rememberMe;
} }
class LoginCommandValidator extends BaseValidator2<LoginCommand> { class LoginCommandValidator extends BaseValidator<LoginCommand> {
public static final LoginCommandValidator INSTANCE = new LoginCommandValidator(); public static final LoginCommandValidator INSTANCE = new LoginCommandValidator();
private LoginCommandValidator() { private LoginCommandValidator() {
ruleFor(LoginCommand::getAccount) ruleForString(LoginCommand::getAccount)
.notNull("邮箱地址不能为空") .notNull("邮箱地址不能为空")
.matchesOr(new String[] { RegexConsts.EMAIL, RegexConsts.MOBILE_PHONE }, value -> new RuntimeException('"' + value + "\" 不是邮箱地址或手机号")); .matchesOr(new String[] { RegexConsts.EMAIL, RegexConsts.MOBILE_PHONE },
ruleFor(LoginCommand::getPwd) value -> new RuntimeException('"' + value + "\" 不是邮箱地址或手机号"));
ruleForString(LoginCommand::getPwd)
.notNull("密码不能为空") .notNull("密码不能为空")
.notEmpty("密码不能为空") .notEmpty("密码不能为空")
.matches(RegexConsts.PASSWORD, "密码格式错误"); .matches(RegexConsts.PASSWORD, "密码格式错误");

View File

@ -15,10 +15,6 @@
<description>参考 DDD 落地的脚手架</description> <description>参考 DDD 落地的脚手架</description>
<properties>
<spring-boot.version>2.7.6</spring-boot.version>
</properties>
<dependencies> <dependencies>
<dependency> <dependency>

View File

@ -0,0 +1,69 @@
spring:
# redis配置
redis:
# Redis数据库索引默认为0
database: 1
# Redis服务器地址
host: 127.0.0.1
# Redis服务器连接端口
port: 6379
# Redis服务器连接密码默认为空
# password:
# 连接超时时间
timeout: 10s
lettuce:
pool:
# 连接池最大连接数
max-active: 200
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
# 连接池中的最大空闲连接
max-idle: 10
# 连接池中的最小空闲连接
min-idle: 0
# 数据库
datasource:
url: jdbc:postgresql://localhost:5432/plusone
username: plusone
password: XXXXXXXXXXXXXXXX
plusone:
application:
name: plusone
server:
port: 8108
debug: true
# 短信发送相关参数
sms:
region: ap-guangzhou
credential:
secret-id: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
secret-key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
client:
# SDK 默认用 TC3-HMAC-SHA256 进行签名,非必要请不要修改这个字段
sign-method: HmacSHA256
http:
# proxy:
# host: xxx
# port: xxx
req-method: POST
conn-timeout: 60
app-id: 1111111111
templates:
code: 0000000
# 邮件发送相关参数
mail:
host: smtp.163.com
#设置邮件发送者
from: example@163.com
password: XXXXXXXXXXXXXXXX
# 异常拦截机制是否拦截所有异常
exception:
handle-all-exception: false
# 日志配置
logging:
level:
root: debug

View File

@ -1,79 +1,11 @@
spring:
profiles:
active: public
plusone: plusone:
application:
name: plusone
server:
port: 8108
debug: true
# 短信发送相关参数
sms:
region: ap-guangzhou
credential:
secret-id: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
secret-key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
client:
# SDK 默认用 TC3-HMAC-SHA256 进行签名,非必要请不要修改这个字段
sign-method: HmacSHA256
http:
# proxy:
# host: xxx
# port: xxx
req-method: POST
conn-timeout: 60
app-id: 1111111111
templates:
code: 0000000
# 邮件发送相关参数 # 邮件发送相关参数
mail: mail:
host: smtp.163.com
#设置邮件发送者
from: example@163.com
password: XXXXXXXXXXXXXXXX
subject: subject:
code: Plusone code: Plusone
template: template:
code: 【Plusone】验证码%s10分钟内有效请勿泄露。 code: 【Plusone】验证码%s10分钟内有效请勿泄露。
# 异常拦截机制是否拦截所有异常
exception:
handle-all-exception: false
spring:
# redis配置
redis:
# Redis数据库索引默认为0
database: 1
# Redis服务器地址
host: 127.0.0.1
# Redis服务器连接端口
port: 6379
# Redis服务器连接密码默认为空
# password:
# 连接超时时间
timeout: 10s
lettuce:
pool:
# 连接池最大连接数
max-active: 200
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
# 连接池中的最大空闲连接
max-idle: 10
# 连接池中的最小空闲连接
min-idle: 0
# 数据库
datasource:
url: jdbc:postgresql://localhost:5432/plusone
username: plusone
password: XXXXXXXXXXXXXXXX
# 日志配置
logging:
file:
name: ${user.home}/logs/${plusone.application.name}.log
level:
root: INFO
xyz.zhouxy.plusone: DEBUG
org.springframework.jdbc.core: DEBUG
xyz.zhouxy.plusone.system.application.query: DEBUG

View File

@ -10,23 +10,23 @@
</encoder> </encoder>
</appender> </appender>
<!-- <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder> <encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %5level ${PID:- } - [%15.15t] %-50.50logger : %msg%n</pattern> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %5level ${PID:- } - [%15.15t] %-50.50logger : %msg%n</pattern>
<charset>utf-8</charset> <charset>utf-8</charset>
</encoder> </encoder>
<file>log/output.log</file> <file>log/plusone.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>log/output.log.%i</fileNamePattern> <fileNamePattern>log/plusone.log.%i</fileNamePattern>
</rollingPolicy> </rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>20MB</MaxFileSize> <MaxFileSize>20MB</MaxFileSize>
</triggeringPolicy> </triggeringPolicy>
</appender> --> </appender>
<root level="INFO"> <root level="INFO">
<appender-ref ref="CONSOLE" /> <appender-ref ref="CONSOLE" />
<!-- <appender-ref ref="FILE" /> --> <appender-ref ref="FILE" />
</root> </root>
</configuration> </configuration>

View File

@ -0,0 +1,25 @@
package xyz.zhouxy.plusone.system.application.exception.handler;
import javax.annotation.Nonnull;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler;
import xyz.zhouxy.plusone.exception.handler.ExceptionInfoHolderFactory;
import xyz.zhouxy.plusone.system.application.exception.AccountLoginException;
import xyz.zhouxy.plusone.util.RestfulResult;
@RestControllerAdvice
public class AccountLoginExceptionHandler extends BaseExceptionHandler {
protected AccountLoginExceptionHandler() {
super(ExceptionInfoHolderFactory.newDefaultExceptionInfoHolder());
}
@ExceptionHandler({ AccountLoginException.class })
public ResponseEntity<RestfulResult> handleException(@Nonnull Exception e) {
return buildExceptionResponse(e);
}
}

View File

@ -15,6 +15,7 @@ import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.exception.SameTokenInvalidException; import cn.dev33.satoken.exception.SameTokenInvalidException;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler; import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler;
import xyz.zhouxy.plusone.exception.handler.ExceptionInfoHolderFactory;
import xyz.zhouxy.plusone.util.RestfulResult; import xyz.zhouxy.plusone.util.RestfulResult;
/** /**
@ -26,8 +27,8 @@ import xyz.zhouxy.plusone.util.RestfulResult;
@Slf4j @Slf4j
public class SaTokenExceptionHandler extends BaseExceptionHandler { public class SaTokenExceptionHandler extends BaseExceptionHandler {
public SaTokenExceptionHandler(ExceptionInfoHolder exceptionInfoHolder) { public SaTokenExceptionHandler() {
super(exceptionInfoHolder); super(ExceptionInfoHolderFactory.newDefaultExceptionInfoHolder());
set(NotPermissionException.class, 4030103, "会话未能通过权限认证", HttpStatus.FORBIDDEN); set(NotPermissionException.class, 4030103, "会话未能通过权限认证", HttpStatus.FORBIDDEN);
set(NotRoleException.class, 4030103, "会话未能通过角色认证", HttpStatus.FORBIDDEN); set(NotRoleException.class, 4030103, "会话未能通过角色认证", HttpStatus.FORBIDDEN);
set(DisableServiceException.class, 4030202, "账号指定服务已被封禁", HttpStatus.FORBIDDEN); set(DisableServiceException.class, 4030202, "账号指定服务已被封禁", HttpStatus.FORBIDDEN);
@ -36,7 +37,7 @@ public class SaTokenExceptionHandler extends BaseExceptionHandler {
set(NotSafeException.class, 4020300, "会话未能通过二级认证", HttpStatus.UNAUTHORIZED); set(NotSafeException.class, 4020300, "会话未能通过二级认证", HttpStatus.UNAUTHORIZED);
set(NotLoginException.class, set(NotLoginException.class,
4020400, 4020400,
e -> switch (((NotLoginException) e).getType()) { e -> switch (e.getType()) {
case NotLoginException.NOT_TOKEN -> "未提供 Token"; case NotLoginException.NOT_TOKEN -> "未提供 Token";
case NotLoginException.INVALID_TOKEN -> "Token 无效"; case NotLoginException.INVALID_TOKEN -> "Token 无效";
case NotLoginException.TOKEN_TIMEOUT -> "Token 已过期"; case NotLoginException.TOKEN_TIMEOUT -> "Token 已过期";

View File

@ -2,12 +2,12 @@ package xyz.zhouxy.plusone.system.application.query;
import java.util.List; import java.util.List;
import org.apache.ibatis.jdbc.SQL;
import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource; import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import xyz.zhouxy.plusone.sql.SQL;
import xyz.zhouxy.plusone.system.application.query.params.DictQueryParams; import xyz.zhouxy.plusone.system.application.query.params.DictQueryParams;
import xyz.zhouxy.plusone.system.application.query.result.DictOverview; import xyz.zhouxy.plusone.system.application.query.result.DictOverview;
@ -26,14 +26,21 @@ public class DictQueries {
} }
public List<DictOverview> queryDictOverviewList(DictQueryParams queryParams) { public List<DictOverview> queryDictOverviewList(DictQueryParams queryParams) {
String sql = new SQL() String sql = new SQL() {
.SELECT("id", "dict_type", "dict_label", {
"created_by", "create_time", "updated_by", "update_time", "count") SELECT("id", "dict_type", "dict_label",
.FROM("view_sys_dict_overview") "created_by", "create_time", "updated_by", "update_time", "count");
.WHERE_IF(queryParams.getDictType() != null, "dict_type LIKE '%:dictType%'") FROM("view_sys_dict_overview");
.WHERE_IF(queryParams.getDictLabel() != null, "dict_label LIKE '%:dictLabel%'") if (queryParams.getDictType() != null) {
.toString(); WHERE("dict_type LIKE '%:dictType%'");
}
if (queryParams.getDictLabel() != null) {
WHERE("dict_label LIKE '%:dictLabel%'");
}
}
}.toString();
return this.jdbcTemplate return this.jdbcTemplate
.query(sql, new BeanPropertySqlParameterSource(queryParams), new BeanPropertyRowMapper<>(DictOverview.class)); .query(sql, new BeanPropertySqlParameterSource(queryParams),
new BeanPropertyRowMapper<>(DictOverview.class));
} }
} }

View File

@ -7,7 +7,7 @@ import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import xyz.zhouxy.plusone.sql.SQL; import org.apache.ibatis.jdbc.SQL;
import xyz.zhouxy.plusone.system.application.query.params.RoleQueryParams; import xyz.zhouxy.plusone.system.application.query.params.RoleQueryParams;
import xyz.zhouxy.plusone.system.application.query.result.RoleOverview; import xyz.zhouxy.plusone.system.application.query.result.RoleOverview;
@ -35,30 +35,47 @@ public class RoleQueries {
* @return * @return
*/ */
public List<RoleOverview> query(RoleQueryParams params) { public List<RoleOverview> query(RoleQueryParams params) {
String b = new SQL() var sql = new SQL() {
.SELECT("id") {
.FROM("sys_role") SELECT("a.id AS id", "a.name AS name", "a.identifier AS identifier", "a.status AS status");
.WHERE_IF_NOT_NULL(params.getId(), "id = :id") FROM("sys_role AS a", "(" +
.WHERE_IF_NOT_NULL(params.getName(), "name = :name") new SQL() {
.WHERE_IF_NOT_NULL(params.getIdentifier(), "identifier = :identifier") {
.WHERE_IF_NOT_NULL(params.getStatus(), "status = :status") SELECT("id");
.WHERE_IF_NOT_NULL(params.getCreateTimeStart(), "create_time >= :createTimeStart") FROM("sys_role");
.WHERE_IF_NOT_NULL(params.getCreateTimeEnd(), "create_time < :createTimeEnd") if (null != params.getId()) {
.WHERE_IF_NOT_NULL(params.getUpdateTimeStart(), "update_time >= :updateTimeStart") WHERE("id = :id");
.WHERE_IF_NOT_NULL(params.getUpdateTimeEnd(), "update_time < :updateTimeEnd") }
.LIMIT(params.getSize()) if (null != params.getName()) {
.OFFSET(params.getOffset()) WHERE("name = :name");
.toString(); }
var sql = """ if (null != params.getIdentifier()) {
SELECT a.id AS id, a.name AS name, a.identifier AS identifier, a.status AS status WHERE("identifier = :identifier");
FROM sys_role AS a, ( }
""" + b + """ if (null != params.getStatus()) {
) AS b WHERE("status = :status");
WHERE a.id = b.id }
"""; if (null != params.getCreateTimeStart()) {
WHERE("create_time >= :createTimeStart");
}
if (null != params.getCreateTimeEnd()) {
WHERE("create_time < :createTimeEnd");
}
if (null != params.getUpdateTimeStart()) {
WHERE("update_time >= :updateTimeStart");
}
if (null != params.getUpdateTimeEnd()) {
WHERE("update_time < :updateTimeEnd");
}
LIMIT(params.getSize());
OFFSET(params.getOffset());
}
}.toString() + ") AS b");
WHERE("a.id = b.id");
}
}.toString();
return this.jdbcTemplate return this.jdbcTemplate
.query(sql, new BeanPropertySqlParameterSource(params), .query(sql, new BeanPropertySqlParameterSource(params),
new BeanPropertyRowMapper<>(RoleOverview.class)); new BeanPropertyRowMapper<>(RoleOverview.class));
} }
} }

View File

@ -16,6 +16,7 @@ import xyz.zhouxy.plusone.system.domain.model.account.AccountStatus;
import xyz.zhouxy.plusone.system.domain.model.account.Email; import xyz.zhouxy.plusone.system.domain.model.account.Email;
import xyz.zhouxy.plusone.system.domain.model.account.MobilePhone; import xyz.zhouxy.plusone.system.domain.model.account.MobilePhone;
import xyz.zhouxy.plusone.system.domain.model.account.Password; import xyz.zhouxy.plusone.system.domain.model.account.Password;
import xyz.zhouxy.plusone.system.domain.model.account.Sex;
import xyz.zhouxy.plusone.system.domain.model.account.Username; import xyz.zhouxy.plusone.system.domain.model.account.Username;
import xyz.zhouxy.plusone.validator.InvalidInputException; import xyz.zhouxy.plusone.validator.InvalidInputException;
@ -78,10 +79,10 @@ public class RegisterAccountService {
Username.of(username), Username.of(username),
email, email,
mobilePhone, mobilePhone,
Password.newPassword(command.getPassword(), command.getPasswordConfirmation()), Password.newPassword(command.getPassword(), command.getReenteredPassword()),
AccountStatus.AVAILABLE, AccountStatus.AVAILABLE,
Set.of(DEFAULT_ROLE_ID), Set.of(DEFAULT_ROLE_ID),
AccountInfo.of(command.getNickname(), command.getAvatar(), command.getSex())); AccountInfo.of(command.getNickname(), null, Sex.UNSET));
accountRepository.save(accountToSave); accountRepository.save(accountToSave);
} }

View File

@ -3,12 +3,9 @@ package xyz.zhouxy.plusone.system.application.service.command;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern; import javax.validation.constraints.Pattern;
import org.hibernate.validator.constraints.URL;
import lombok.Data; import lombok.Data;
import xyz.zhouxy.plusone.constant.RegexConsts; import xyz.zhouxy.plusone.constant.RegexConsts;
import xyz.zhouxy.plusone.domain.ICommand; import xyz.zhouxy.plusone.domain.ICommand;
import xyz.zhouxy.plusone.system.domain.model.account.Sex;
/** /**
* *
@ -32,14 +29,8 @@ public class RegisterAccountCommand implements ICommand {
@NotBlank @NotBlank
@Pattern(regexp = RegexConsts.PASSWORD) @Pattern(regexp = RegexConsts.PASSWORD)
String password; String password;
String passwordConfirmation; String reenteredPassword;
@Pattern(regexp = RegexConsts.NICKNAME) @Pattern(regexp = RegexConsts.NICKNAME)
String nickname; String nickname;
@NotBlank
@URL
String avatar;
Sex sex;
} }

View File

@ -1,13 +1,11 @@
package xyz.zhouxy.plusone.system.application.service.command.validator; package xyz.zhouxy.plusone.system.application.service.command.validator;
import java.util.regex.Pattern; import java.util.List;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import xyz.zhouxy.plusone.constant.RegexConsts; import xyz.zhouxy.plusone.constant.RegexConsts;
import xyz.zhouxy.plusone.system.application.service.command.LoginByOtpCommand; import xyz.zhouxy.plusone.system.application.service.command.LoginByOtpCommand;
import xyz.zhouxy.plusone.util.RegexUtil;
import xyz.zhouxy.plusone.validator.BaseValidator; import xyz.zhouxy.plusone.validator.BaseValidator;
import xyz.zhouxy.plusone.validator.DtoValidator; import xyz.zhouxy.plusone.validator.DtoValidator;
@ -15,15 +13,13 @@ import xyz.zhouxy.plusone.validator.DtoValidator;
@DtoValidator(LoginByOtpCommand.class) @DtoValidator(LoginByOtpCommand.class)
public class LoginByOtpCommandValidator extends BaseValidator<LoginByOtpCommand> { public class LoginByOtpCommandValidator extends BaseValidator<LoginByOtpCommand> {
public LoginByOtpCommandValidator() { public LoginByOtpCommandValidator() {
withRule(loginCommand -> { ruleForString(LoginByOtpCommand::getPrincipal)
String principal = loginCommand.getPrincipal(); .notNull("输入邮箱地址或手机号")
return StringUtils.hasText(principal) .notEmpty("输入邮箱地址或手机号")
&& .matchesOr(List.of(RegexConsts.EMAIL, RegexConsts.MOBILE_PHONE), "输入用户名、邮箱地址或手机号");
RegexUtil.matchesOr(principal, RegexConsts.EMAIL, RegexConsts.MOBILE_PHONE); ruleForString(LoginByOtpCommand::getOtp)
}, "输入邮箱地址或手机号"); .notNull("验证码不能为空")
withRule(loginCommand -> { .notEmpty("验证码不能为空")
String otp = loginCommand.getOtp(); .matches(RegexConsts.CAPTCHA, "验证码格式不正确");
return StringUtils.hasText(otp) && Pattern.matches(RegexConsts.CAPTCHA, otp);
}, "验证码不符合要求");
} }
} }

View File

@ -1,13 +1,9 @@
package xyz.zhouxy.plusone.system.application.service.command.validator; package xyz.zhouxy.plusone.system.application.service.command.validator;
import java.util.regex.Pattern; import java.util.List;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import xyz.zhouxy.plusone.constant.RegexConsts; import xyz.zhouxy.plusone.constant.RegexConsts;
import xyz.zhouxy.plusone.system.application.service.command.LoginByPasswordCommand; import xyz.zhouxy.plusone.system.application.service.command.LoginByPasswordCommand;
import xyz.zhouxy.plusone.util.RegexUtil;
import xyz.zhouxy.plusone.validator.BaseValidator; import xyz.zhouxy.plusone.validator.BaseValidator;
import xyz.zhouxy.plusone.validator.DtoValidator; import xyz.zhouxy.plusone.validator.DtoValidator;
@ -15,17 +11,14 @@ import xyz.zhouxy.plusone.validator.DtoValidator;
@DtoValidator(LoginByPasswordCommand.class) @DtoValidator(LoginByPasswordCommand.class)
public class LoginByPasswordCommandValidator extends BaseValidator<LoginByPasswordCommand> { public class LoginByPasswordCommandValidator extends BaseValidator<LoginByPasswordCommand> {
public LoginByPasswordCommandValidator() { public LoginByPasswordCommandValidator() {
withRule(loginCommand -> { ruleForString(LoginByPasswordCommand::getPrincipal)
String principal = loginCommand.getPrincipal(); .notNull("输入用户名、邮箱地址或手机号")
return StringUtils.hasText(principal) .notEmpty("输入用户名、邮箱地址或手机号")
&& .matchesOr(List.of(RegexConsts.USERNAME, RegexConsts.EMAIL, RegexConsts.MOBILE_PHONE),
RegexUtil.matchesOr(principal, RegexConsts.USERNAME, RegexConsts.EMAIL, RegexConsts.MOBILE_PHONE, principal); "输入用户名、邮箱地址或手机号");
}, "输入用户名、邮箱地址或手机号"); ruleForString(LoginByPasswordCommand::getPassword)
withRule(loginCommand -> { .notNull("密码不能为空")
String password = loginCommand.getPassword(); .notEmpty("密码不能为空")
return StringUtils.hasText(password) .matches(RegexConsts.PASSWORD, "密码格式不正确");
&&
Pattern.matches(RegexConsts.PASSWORD, password);
}, "密码格式不正确");
} }
} }

45
pom.xml
View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -25,21 +26,23 @@
<maven.compiler.source>17</maven.compiler.source> <maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target> <maven.compiler.target>17</maven.compiler.target>
<spring-boot.version>2.7.6</spring-boot.version> <spring-boot.version>2.7.8</spring-boot.version>
<sa-token.version>1.32.0</sa-token.version> <sa-token.version>1.34.0</sa-token.version>
<hutool.version>5.8.9</hutool.version> <hutool.version>5.8.11</hutool.version>
<mybatis-starter.version>2.2.2</mybatis-starter.version> <mybatis-starter.version>3.0.1</mybatis-starter.version>
<mybatis-plus.version>3.5.2</mybatis-plus.version> <mybatis-plus.version>3.5.3.1</mybatis-plus.version>
<commons-io.version>2.11.0</commons-io.version> <commons-io.version>2.11.0</commons-io.version>
<mica.version>2.7.5</mica.version> <mica.version>2.7.5</mica.version>
<mapstruct.version>1.5.3.Final</mapstruct.version> <mapstruct.version>1.5.3.Final</mapstruct.version>
<guava.version>30.1-jre</guava.version> <guava.version>31.1-jre</guava.version>
<commons-lang3.version>3.12.0</commons-lang3.version> <commons-lang3.version>3.12.0</commons-lang3.version>
<commons-collections4.version>4.4</commons-collections4.version> <commons-collections4.version>4.4</commons-collections4.version>
<commons-math3.version>3.6.1</commons-math3.version> <commons-math3.version>3.6.1</commons-math3.version>
<commons-pool2.version>2.11.1</commons-pool2.version> <commons-pool2.version>2.11.1</commons-pool2.version>
<okio.version>1.12.0</okio.version> <tencentcloud-sdk.version>3.1.681</tencentcloud-sdk.version>
<tencentcloud-sdk.version>3.1.622</tencentcloud-sdk.version> <fastdfs.version>1.29-SNAPSHOT</fastdfs.version>
<okio.version>3.0.0</okio.version>
<okhttp.version>4.10.0</okhttp.version>
<plusone-basic.version>1.0.0-SNAPSHOT</plusone-basic.version> <plusone-basic.version>1.0.0-SNAPSHOT</plusone-basic.version>
<plusone-system.version>1.0.0-SNAPSHOT</plusone-system.version> <plusone-system.version>1.0.0-SNAPSHOT</plusone-system.version>
@ -126,12 +129,6 @@
<version>${mica.version}</version> <version>${mica.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.squareup.okio</groupId>
<artifactId>okio</artifactId>
<version>${okio.version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
@ -169,6 +166,24 @@
<artifactId>commons-pool2</artifactId> <artifactId>commons-pool2</artifactId>
<version>${commons-pool2.version}</version> <version>${commons-pool2.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.csource</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>${fastdfs.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>${okhttp.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.okio</groupId>
<artifactId>okio</artifactId>
<version>${okio.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>