From cf96d8037dfc4ccb2c88086f39781da52464f0cb Mon Sep 17 00:00:00 2001 From: FatttSnake Date: Fri, 22 Dec 2023 18:02:42 +0800 Subject: [PATCH] Add account register and verify api --- .../top/fatweb/api/config/InitConfig.kt | 3 +- .../fatweb/api/config/MybatisPlusConfig.kt | 1 - .../top/fatweb/api/config/SecurityConfig.kt | 1 + .../fatweb/api/config/VelocityEngineConfig.kt | 17 ++++ .../permission/AuthenticationController.kt | 14 +++ .../api/converter/permission/UserConverter.kt | 2 + .../fatweb/api/entity/common/ResponseCode.kt | 6 +- .../api/exception/AccountNeedInitException.kt | 3 + .../api/exception/NoEmailConfigException.kt | 5 ++ .../NoVerificationRequiredException.kt | 3 + ...VerificationCodeErrorOrExpiredException.kt | 3 + .../fatweb/api/handler/ExceptionHandler.kt | 19 ++++- .../api/param/permission/RegisterParam.kt | 18 +++- .../api/param/permission/VerifyParam.kt | 9 -- .../permission/IAuthenticationService.kt | 8 ++ .../impl/AuthenticationServiceImpl.kt | 71 +++++++++++++++- .../system/impl/SettingsServiceImpl.kt | 1 + .../kotlin/top/fatweb/api/util/MailUtil.kt | 24 +++--- .../api/vo/permission/UserWithInfoVo.kt | 9 ++ .../api/vo/permission/UserWithPowerInfoVo.kt | 9 ++ .../V1_0_0_231019__Add_table_'t_user'.sql | 2 +- .../mapper/permission/UserMapper.xml | 7 +- .../templates/email-verify-account-cn.vm | 85 +++++++++++++++++++ 23 files changed, 289 insertions(+), 31 deletions(-) create mode 100644 src/main/kotlin/top/fatweb/api/config/VelocityEngineConfig.kt create mode 100644 src/main/kotlin/top/fatweb/api/exception/AccountNeedInitException.kt create mode 100644 src/main/kotlin/top/fatweb/api/exception/NoEmailConfigException.kt create mode 100644 src/main/kotlin/top/fatweb/api/exception/NoVerificationRequiredException.kt create mode 100644 src/main/kotlin/top/fatweb/api/exception/VerificationCodeErrorOrExpiredException.kt create mode 100644 src/main/resources/templates/email-verify-account-cn.vm diff --git a/src/main/kotlin/top/fatweb/api/config/InitConfig.kt b/src/main/kotlin/top/fatweb/api/config/InitConfig.kt index e221b98..f20b707 100644 --- a/src/main/kotlin/top/fatweb/api/config/InitConfig.kt +++ b/src/main/kotlin/top/fatweb/api/config/InitConfig.kt @@ -2,6 +2,7 @@ package top.fatweb.api.config import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper import jakarta.annotation.PostConstruct +import org.apache.velocity.app.VelocityEngine import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.context.annotation.DependsOn @@ -29,7 +30,7 @@ import top.fatweb.avatargenerator.GitHubAvatar class InitConfig( private val userService: IUserService, private val userInfoService: IUserInfoService, - private val passwordEncoder: PasswordEncoder, + private val passwordEncoder: PasswordEncoder ) { private val logger: Logger = LoggerFactory.getLogger(this::class.java) diff --git a/src/main/kotlin/top/fatweb/api/config/MybatisPlusConfig.kt b/src/main/kotlin/top/fatweb/api/config/MybatisPlusConfig.kt index cb28fd3..83d7dec 100644 --- a/src/main/kotlin/top/fatweb/api/config/MybatisPlusConfig.kt +++ b/src/main/kotlin/top/fatweb/api/config/MybatisPlusConfig.kt @@ -22,5 +22,4 @@ class MybatisPlusConfig { return mybatisPlusInterceptor } - } \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/config/SecurityConfig.kt b/src/main/kotlin/top/fatweb/api/config/SecurityConfig.kt index ab735fe..6a4424c 100644 --- a/src/main/kotlin/top/fatweb/api/config/SecurityConfig.kt +++ b/src/main/kotlin/top/fatweb/api/config/SecurityConfig.kt @@ -75,6 +75,7 @@ class SecurityConfig( "/swagger-ui.html", "/favicon.ico", "/login", + "/register" ).anonymous() // Authentication required .anyRequest().authenticated() diff --git a/src/main/kotlin/top/fatweb/api/config/VelocityEngineConfig.kt b/src/main/kotlin/top/fatweb/api/config/VelocityEngineConfig.kt new file mode 100644 index 0000000..fd97e7d --- /dev/null +++ b/src/main/kotlin/top/fatweb/api/config/VelocityEngineConfig.kt @@ -0,0 +1,17 @@ +package top.fatweb.api.config + +import org.apache.velocity.app.VelocityEngine +import org.apache.velocity.runtime.RuntimeConstants +import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +class VelocityEngineConfig { + @Bean + fun velocityEngine() = VelocityEngine().apply { + setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath") + setProperty("classpath.resource.loader.class", ClasspathResourceLoader::class.java.name) + init() + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/controller/permission/AuthenticationController.kt b/src/main/kotlin/top/fatweb/api/controller/permission/AuthenticationController.kt index 0373356..6db34c2 100644 --- a/src/main/kotlin/top/fatweb/api/controller/permission/AuthenticationController.kt +++ b/src/main/kotlin/top/fatweb/api/controller/permission/AuthenticationController.kt @@ -42,6 +42,20 @@ class AuthenticationController( return ResponseResult.success(ResponseCode.PERMISSION_REGISTER_SUCCESS) } + /** + * Send verify email + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Operation(summary = "发送验证邮箱") + @PostMapping("/resend") + fun resend(): ResponseResult { + authenticationService.resend() + + return ResponseResult.success(ResponseCode.PERMISSION_RESEND_SUCCESS) + } + /** * Verify * diff --git a/src/main/kotlin/top/fatweb/api/converter/permission/UserConverter.kt b/src/main/kotlin/top/fatweb/api/converter/permission/UserConverter.kt index 4870ba9..13a2964 100644 --- a/src/main/kotlin/top/fatweb/api/converter/permission/UserConverter.kt +++ b/src/main/kotlin/top/fatweb/api/converter/permission/UserConverter.kt @@ -34,6 +34,7 @@ object UserConverter { fun userToUserWithPowerInfoVo(user: User) = UserWithPowerInfoVo( id = user.id, username = user.username, + verified = user.verify.isNullOrBlank(), locking = user.locking?.let { it == 1 }, expiration = user.expiration, credentialsExpiration = user.credentialsExpiration, @@ -109,6 +110,7 @@ object UserConverter { fun userToUserWithInfoVo(user: User) = UserWithInfoVo( id = user.id, username = user.username, + verified = user.verify.isNullOrBlank(), locking = user.locking?.let { it == 1 }, expiration = user.expiration, credentialsExpiration = user.credentialsExpiration, diff --git a/src/main/kotlin/top/fatweb/api/entity/common/ResponseCode.kt b/src/main/kotlin/top/fatweb/api/entity/common/ResponseCode.kt index 0e15f8d..af874cb 100644 --- a/src/main/kotlin/top/fatweb/api/entity/common/ResponseCode.kt +++ b/src/main/kotlin/top/fatweb/api/entity/common/ResponseCode.kt @@ -19,7 +19,8 @@ enum class ResponseCode(val code: Int) { PERMISSION_LOGOUT_SUCCESS(BusinessCode.PERMISSION, 2), PERMISSION_TOKEN_RENEW_SUCCESS(BusinessCode.PERMISSION, 3), PERMISSION_REGISTER_SUCCESS(BusinessCode.PERMISSION, 4), - PERMISSION_VERIFY_SUCCESS(BusinessCode.PERMISSION, 5), + PERMISSION_RESEND_SUCCESS(BusinessCode.PERMISSION, 5), + PERMISSION_VERIFY_SUCCESS(BusinessCode.PERMISSION, 6), PERMISSION_UNAUTHORIZED(BusinessCode.PERMISSION, 50), PERMISSION_USERNAME_NOT_FOUND(BusinessCode.PERMISSION, 51), @@ -33,6 +34,9 @@ enum class ResponseCode(val code: Int) { PERMISSION_LOGOUT_FAILED(BusinessCode.PERMISSION, 59), PERMISSION_TOKEN_ILLEGAL(BusinessCode.PERMISSION, 60), PERMISSION_TOKEN_HAS_EXPIRED(BusinessCode.PERMISSION, 61), + PERMISSION_NO_VERIFICATION_REQUIRED(BusinessCode.PERMISSION, 62), + PERMISSION_VERIFY_CODE_ERROR_OR_EXPIRED(BusinessCode.PERMISSION, 63), + PERMISSION_ACCOUNT_NEED_INIT(BusinessCode.PERMISSION, 64), DATABASE_SELECT_SUCCESS(BusinessCode.DATABASE, 0), DATABASE_SELECT_FAILED(BusinessCode.DATABASE, 5), diff --git a/src/main/kotlin/top/fatweb/api/exception/AccountNeedInitException.kt b/src/main/kotlin/top/fatweb/api/exception/AccountNeedInitException.kt new file mode 100644 index 0000000..e46093a --- /dev/null +++ b/src/main/kotlin/top/fatweb/api/exception/AccountNeedInitException.kt @@ -0,0 +1,3 @@ +package top.fatweb.api.exception + +class AccountNeedInitException : RuntimeException("Account need initialize") \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/exception/NoEmailConfigException.kt b/src/main/kotlin/top/fatweb/api/exception/NoEmailConfigException.kt new file mode 100644 index 0000000..07fdf50 --- /dev/null +++ b/src/main/kotlin/top/fatweb/api/exception/NoEmailConfigException.kt @@ -0,0 +1,5 @@ +package top.fatweb.api.exception + +class NoEmailConfigException( + vararg configs: String +) : RuntimeException("Email settings not configured: ${configs.joinToString(", ")}") \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/exception/NoVerificationRequiredException.kt b/src/main/kotlin/top/fatweb/api/exception/NoVerificationRequiredException.kt new file mode 100644 index 0000000..46a6233 --- /dev/null +++ b/src/main/kotlin/top/fatweb/api/exception/NoVerificationRequiredException.kt @@ -0,0 +1,3 @@ +package top.fatweb.api.exception + +class NoVerificationRequiredException : RuntimeException("No verification required") \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/exception/VerificationCodeErrorOrExpiredException.kt b/src/main/kotlin/top/fatweb/api/exception/VerificationCodeErrorOrExpiredException.kt new file mode 100644 index 0000000..fcd3cd9 --- /dev/null +++ b/src/main/kotlin/top/fatweb/api/exception/VerificationCodeErrorOrExpiredException.kt @@ -0,0 +1,3 @@ +package top.fatweb.api.exception + +class VerificationCodeErrorOrExpiredException : RuntimeException("Verification code is error or has expired") \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/handler/ExceptionHandler.kt b/src/main/kotlin/top/fatweb/api/handler/ExceptionHandler.kt index 10a32b5..ec1f87b 100644 --- a/src/main/kotlin/top/fatweb/api/handler/ExceptionHandler.kt +++ b/src/main/kotlin/top/fatweb/api/handler/ExceptionHandler.kt @@ -16,8 +16,7 @@ import org.springframework.web.bind.annotation.ExceptionHandler import org.springframework.web.bind.annotation.RestControllerAdvice import top.fatweb.api.entity.common.ResponseCode import top.fatweb.api.entity.common.ResponseResult -import top.fatweb.api.exception.NoRecordFoundException -import top.fatweb.api.exception.TokenHasExpiredException +import top.fatweb.api.exception.* import top.fatweb.avatargenerator.AvatarException /** @@ -122,6 +121,22 @@ class ExceptionHandler { ResponseResult.fail(ResponseCode.PERMISSION_ACCESS_DENIED, "Access Denied", null) } + is NoVerificationRequiredException -> { + logger.debug(e.localizedMessage, e) + ResponseResult.fail(ResponseCode.PERMISSION_NO_VERIFICATION_REQUIRED, e.localizedMessage, null) + } + + is VerificationCodeErrorOrExpiredException -> { + logger.debug(e.localizedMessage, e) + ResponseResult.fail(ResponseCode.PERMISSION_VERIFY_CODE_ERROR_OR_EXPIRED, e.localizedMessage, null) + } + + is AccountNeedInitException -> { + logger.debug(e.localizedMessage, e) + ResponseResult.fail(ResponseCode.PERMISSION_ACCOUNT_NEED_INIT, e.localizedMessage, null) + } + + is BadSqlGrammarException -> { logger.debug(e.localizedMessage, e) ResponseResult.fail(ResponseCode.DATABASE_EXECUTE_ERROR, "Incorrect SQL syntax", null) diff --git a/src/main/kotlin/top/fatweb/api/param/permission/RegisterParam.kt b/src/main/kotlin/top/fatweb/api/param/permission/RegisterParam.kt index 3b3a019..3ea3148 100644 --- a/src/main/kotlin/top/fatweb/api/param/permission/RegisterParam.kt +++ b/src/main/kotlin/top/fatweb/api/param/permission/RegisterParam.kt @@ -1,8 +1,9 @@ package top.fatweb.api.param.permission import io.swagger.v3.oas.annotations.media.Schema -import jakarta.validation.constraints.Email import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size /** * Register parameters @@ -12,6 +13,17 @@ import jakarta.validation.constraints.NotBlank */ @Schema(description = "注册请求参数") data class RegisterParam( + /** + * Username + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "用户名", example = "abc", required = true) + @field:NotBlank(message = "Username can not be blank") + @field:Pattern(regexp = "[a-zA-Z-_][0-9a-zA-Z-_]{2,38}", message = "Illegal username") + val username: String?, + /** * Email * @@ -19,7 +31,8 @@ data class RegisterParam( * @since 1.0.0 */ @Schema(description = "邮箱", example = "guest@fatweb.top", required = true) - @field:Email(message = "Illegal email address") + @field:NotBlank(message = "Email can not be blank") + @field:Pattern(regexp = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*\$", message = "Illegal email address") val email: String?, /** @@ -30,5 +43,6 @@ data class RegisterParam( */ @Schema(description = "密码", example = "test123456", required = true) @field:NotBlank(message = "Password can not be blank") + @field:Size(min = 10, max = 30) val password: String? ) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/param/permission/VerifyParam.kt b/src/main/kotlin/top/fatweb/api/param/permission/VerifyParam.kt index 8656056..c98f2c0 100644 --- a/src/main/kotlin/top/fatweb/api/param/permission/VerifyParam.kt +++ b/src/main/kotlin/top/fatweb/api/param/permission/VerifyParam.kt @@ -21,15 +21,6 @@ data class VerifyParam( @field:NotBlank(message = "Code can not be blank") val code: String?, - /** - * Username - * - * @author FatttSnake, fatttsnake@gmail.com - * @since 1.0.0 - */ - @Schema(description = "用户名", example = "adb") - val username: String?, - /** * Nickname * diff --git a/src/main/kotlin/top/fatweb/api/service/permission/IAuthenticationService.kt b/src/main/kotlin/top/fatweb/api/service/permission/IAuthenticationService.kt index f1ee71e..11c0c25 100644 --- a/src/main/kotlin/top/fatweb/api/service/permission/IAuthenticationService.kt +++ b/src/main/kotlin/top/fatweb/api/service/permission/IAuthenticationService.kt @@ -23,6 +23,14 @@ interface IAuthenticationService { */ fun register(registerParam: RegisterParam) + /** + * Send verify email + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun resend() + /** * Verify * diff --git a/src/main/kotlin/top/fatweb/api/service/permission/impl/AuthenticationServiceImpl.kt b/src/main/kotlin/top/fatweb/api/service/permission/impl/AuthenticationServiceImpl.kt index bbfeec7..41f5331 100644 --- a/src/main/kotlin/top/fatweb/api/service/permission/impl/AuthenticationServiceImpl.kt +++ b/src/main/kotlin/top/fatweb/api/service/permission/impl/AuthenticationServiceImpl.kt @@ -2,8 +2,11 @@ package top.fatweb.api.service.permission.impl import com.baomidou.mybatisplus.extension.kotlin.KtUpdateWrapper import jakarta.servlet.http.HttpServletRequest +import org.apache.velocity.VelocityContext +import org.apache.velocity.app.VelocityEngine import org.slf4j.Logger import org.slf4j.LoggerFactory +import org.springframework.security.access.AccessDeniedException import org.springframework.security.authentication.AuthenticationManager import org.springframework.security.authentication.UsernamePasswordAuthenticationToken import org.springframework.security.crypto.password.PasswordEncoder @@ -14,7 +17,10 @@ import top.fatweb.api.entity.permission.LoginUser import top.fatweb.api.entity.permission.User import top.fatweb.api.entity.permission.UserInfo import top.fatweb.api.entity.system.EventLog +import top.fatweb.api.exception.AccountNeedInitException +import top.fatweb.api.exception.NoVerificationRequiredException import top.fatweb.api.exception.TokenHasExpiredException +import top.fatweb.api.exception.VerificationCodeErrorOrExpiredException import top.fatweb.api.param.permission.LoginParam import top.fatweb.api.param.permission.RegisterParam import top.fatweb.api.param.permission.VerifyParam @@ -24,10 +30,13 @@ import top.fatweb.api.service.permission.IAuthenticationService import top.fatweb.api.service.permission.IUserInfoService import top.fatweb.api.service.permission.IUserService import top.fatweb.api.util.JwtUtil +import top.fatweb.api.util.MailUtil import top.fatweb.api.util.RedisUtil import top.fatweb.api.util.WebUtil import top.fatweb.api.vo.permission.LoginVo import top.fatweb.api.vo.permission.TokenVo +import java.io.StringWriter +import java.time.Instant import java.time.LocalDateTime import java.time.ZoneOffset import java.util.* @@ -44,6 +53,7 @@ import java.util.* */ @Service class AuthenticationServiceImpl( + private val velocityEngine: VelocityEngine, private val authenticationManager: AuthenticationManager, private val passwordEncoder: PasswordEncoder, private val redisUtil: RedisUtil, @@ -56,8 +66,10 @@ class AuthenticationServiceImpl( @Transactional override fun register(registerParam: RegisterParam) { val user = User().apply { - username = "\$UNNAMED_${UUID.randomUUID()}" + username = registerParam.username password = passwordEncoder.encode(registerParam.password) + verify = + "${LocalDateTime.now(ZoneOffset.UTC).toInstant(ZoneOffset.UTC).toEpochMilli()}-${UUID.randomUUID()}" locking = 0 enable = 1 } @@ -67,9 +79,66 @@ class AuthenticationServiceImpl( avatar = avatarService.randomBase64(null).base64 email = registerParam.email }) + + sendVerifyMail(user.username!!, "http://localhost:5173/verify?code=${user.verify!!}", registerParam.email!!) } + @Transactional + override fun resend() { + val user = userService.getById(WebUtil.getLoginUserId()) ?: throw AccessDeniedException("Access Denied") + + user.verify ?: throw NoVerificationRequiredException() + + user.verify = + "${LocalDateTime.now(ZoneOffset.UTC).toInstant(ZoneOffset.UTC).toEpochMilli()}-${UUID.randomUUID()}" + user.updateTime = LocalDateTime.now(ZoneOffset.UTC) + userService.updateById(user) + + WebUtil.getLoginUser()?.user?.userInfo?.email?.let { + sendVerifyMail(user.username!!, "http://localhost:5173/verify?code=${user.verify!!}", it) + } ?: throw AccessDeniedException("Access Denied") + } + + private fun sendVerifyMail(username: String, verifyUrl: String, email: String) { + val velocityContext = VelocityContext().apply { + put("appName", "氮工具") + put("appUrl", "http://localhost:5173/") + put("username", username) + put("verifyUrl", verifyUrl) + } + val template = velocityEngine.getTemplate("templates/email-verify-account-cn.vm") + + val stringWriter = StringWriter() + template.merge(velocityContext, stringWriter) + + MailUtil.sendSimpleMail( + "激活您的账号", stringWriter.toString(), true, + email + ) + } + + @Transactional override fun verify(verifyParam: VerifyParam) { + val user = userService.getById(WebUtil.getLoginUserId()) ?: throw AccessDeniedException("Access Denied") + user.verify ?: throw NoVerificationRequiredException() + if (LocalDateTime.ofInstant(Instant.ofEpochMilli(user.verify!!.split("-").first().toLong()), ZoneOffset.UTC) + .isBefore(LocalDateTime.now(ZoneOffset.UTC).minusHours(2)) || user.verify != verifyParam.code + ) { + throw VerificationCodeErrorOrExpiredException() + } + + if (verifyParam.nickname.isNullOrBlank() || verifyParam.avatar.isNullOrBlank()) { + throw AccountNeedInitException() + } + + userService.update( + KtUpdateWrapper(User()).eq(User::id, user.id).set(User::verify, null) + .set(User::updateTime, LocalDateTime.now(ZoneOffset.UTC)) + ) + userInfoService.update( + KtUpdateWrapper(UserInfo()).eq(UserInfo::userId, user.id).set(UserInfo::nickname, verifyParam.nickname) + .set(UserInfo::avatar, verifyParam.avatar) + ) } @EventLogRecord(EventLog.Event.LOGIN) diff --git a/src/main/kotlin/top/fatweb/api/service/system/impl/SettingsServiceImpl.kt b/src/main/kotlin/top/fatweb/api/service/system/impl/SettingsServiceImpl.kt index 18b97f4..635d110 100644 --- a/src/main/kotlin/top/fatweb/api/service/system/impl/SettingsServiceImpl.kt +++ b/src/main/kotlin/top/fatweb/api/service/system/impl/SettingsServiceImpl.kt @@ -45,6 +45,7 @@ class SettingsServiceImpl : ISettingsService { MailUtil.sendSimpleMail( "${ServerProperties.appName} Test Message", "This is a test email sent when testing the system email sending service.", + false, it ) } diff --git a/src/main/kotlin/top/fatweb/api/util/MailUtil.kt b/src/main/kotlin/top/fatweb/api/util/MailUtil.kt index 9cad5e0..198e7a1 100644 --- a/src/main/kotlin/top/fatweb/api/util/MailUtil.kt +++ b/src/main/kotlin/top/fatweb/api/util/MailUtil.kt @@ -1,8 +1,8 @@ package top.fatweb.api.util -import org.springframework.mail.MailSender -import org.springframework.mail.SimpleMailMessage import org.springframework.mail.javamail.JavaMailSenderImpl +import org.springframework.mail.javamail.MimeMessageHelper +import top.fatweb.api.exception.NoEmailConfigException import top.fatweb.api.settings.MailSecurityType import top.fatweb.api.settings.MailSettings import top.fatweb.api.settings.SettingsOperator @@ -33,15 +33,19 @@ object MailUtil { mailSender.javaMailProperties = properties } - fun getSender(): MailSender = mailSender + fun sendSimpleMail(subject: String, text: String, html: Boolean = false, vararg to: String) { + val fromName = SettingsOperator.getMailValue(MailSettings::fromName) ?: throw NoEmailConfigException("fromName") + val from = SettingsOperator.getMailValue(MailSettings::from) ?: throw NoEmailConfigException("from") - fun sendSimpleMail(subject: String, text: String, vararg to: String) { - mailSender.send(SimpleMailMessage().apply { + val mimeMessage = mailSender.createMimeMessage() + val messageHelper = MimeMessageHelper(mimeMessage, true) + messageHelper.apply { setSubject(subject) - from = "${SettingsOperator.getMailValue(MailSettings::fromName)}<${SettingsOperator.getMailValue(MailSettings::from)}>" - sentDate = Date() - setTo(*to) - setText(text) - }) + setFrom(from, fromName) + setSentDate(Date()) + setTo(to) + setText(text, html) + } + mailSender.send(mimeMessage) } } \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/vo/permission/UserWithInfoVo.kt b/src/main/kotlin/top/fatweb/api/vo/permission/UserWithInfoVo.kt index d6c153e..fc55b20 100644 --- a/src/main/kotlin/top/fatweb/api/vo/permission/UserWithInfoVo.kt +++ b/src/main/kotlin/top/fatweb/api/vo/permission/UserWithInfoVo.kt @@ -32,6 +32,15 @@ data class UserWithInfoVo( @Schema(description = "用户名", example = "User") val username: String?, + /** + * Verified + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "已验证", example = "true") + val verified: Boolean?, + /** * Locking * diff --git a/src/main/kotlin/top/fatweb/api/vo/permission/UserWithPowerInfoVo.kt b/src/main/kotlin/top/fatweb/api/vo/permission/UserWithPowerInfoVo.kt index 652120b..c8409c8 100644 --- a/src/main/kotlin/top/fatweb/api/vo/permission/UserWithPowerInfoVo.kt +++ b/src/main/kotlin/top/fatweb/api/vo/permission/UserWithPowerInfoVo.kt @@ -32,6 +32,15 @@ data class UserWithPowerInfoVo( @Schema(description = "用户名", example = "User") val username: String?, + /** + * Verified + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "已验证", example = "true") + val verified: Boolean?, + /** * Locking * diff --git a/src/main/resources/db/migration/master/V1_0_0_231019__Add_table_'t_user'.sql b/src/main/resources/db/migration/master/V1_0_0_231019__Add_table_'t_user'.sql index b059037..1220681 100644 --- a/src/main/resources/db/migration/master/V1_0_0_231019__Add_table_'t_user'.sql +++ b/src/main/resources/db/migration/master/V1_0_0_231019__Add_table_'t_user'.sql @@ -5,7 +5,7 @@ create table if not exists t_user id bigint not null primary key, username varchar(20) not null comment '用户名', password char(70) not null comment '密码', - verify varchar(36) null comment '验证信息', + verify varchar(50) null comment '验证信息', locking int not null comment '锁定', expiration datetime comment '过期时间', credentials_expiration datetime comment '认证过期时间', diff --git a/src/main/resources/mapper/permission/UserMapper.xml b/src/main/resources/mapper/permission/UserMapper.xml index 52587ee..71e3c93 100644 --- a/src/main/resources/mapper/permission/UserMapper.xml +++ b/src/main/resources/mapper/permission/UserMapper.xml @@ -126,7 +126,7 @@ select t_user.id as user_id, t_user.username as user_username, - t_user.password as user_password, + t_user.verify as user_verify, t_user.locking as user_locking, t_user.expiration as user_expiration, t_user.credentials_expiration as user_credentials_expiration, @@ -224,7 +224,7 @@