Add register and verify to AuthenticationController

This commit is contained in:
2023-12-21 18:35:42 +08:00
parent e7c8311b83
commit c40bb0bbaa
25 changed files with 275 additions and 42 deletions

View File

@@ -36,19 +36,7 @@ class AvatarController(
@Operation(summary = "获取随机头像")
@GetMapping(produces = [MediaType.IMAGE_PNG_VALUE])
fun getRandom(@Valid avatarBaseParam: AvatarBaseParam?): ByteArray =
when ((1..4).random()) {
1 -> avatarService.triangle(avatarBaseParam)
2 -> avatarService.square(avatarBaseParam)
3 -> avatarService.identicon(avatarBaseParam)
else -> avatarService.github(AvatarGitHubParam().apply {
seed = avatarBaseParam?.seed
size = avatarBaseParam?.size
margin = avatarBaseParam?.margin
padding = avatarBaseParam?.padding
colors = avatarBaseParam?.colors
background = avatarBaseParam?.background
})
}
avatarService.random(avatarBaseParam)
/**
* Get random avatar as base64
@@ -67,19 +55,7 @@ class AvatarController(
@Valid avatarBaseParam: AvatarBaseParam?
): ResponseResult<AvatarBase64Vo> =
ResponseResult.success(
ResponseCode.API_AVATAR_SUCCESS, data = when ((1..4).random()) {
1 -> avatarService.triangleBase64(avatarBaseParam)
2 -> avatarService.squareBase64(avatarBaseParam)
3 -> avatarService.identiconBase64(avatarBaseParam)
else -> avatarService.githubBase64(AvatarGitHubParam().apply {
seed = avatarBaseParam?.seed
size = avatarBaseParam?.size
margin = avatarBaseParam?.margin
padding = avatarBaseParam?.padding
colors = avatarBaseParam?.colors
background = avatarBaseParam?.background
})
}
ResponseCode.API_AVATAR_SUCCESS, data = avatarService.randomBase64(avatarBaseParam)
)
/**

View File

@@ -10,6 +10,8 @@ import top.fatweb.api.annotation.BaseController
import top.fatweb.api.entity.common.ResponseCode
import top.fatweb.api.entity.common.ResponseResult
import top.fatweb.api.param.permission.LoginParam
import top.fatweb.api.param.permission.RegisterParam
import top.fatweb.api.param.permission.VerifyParam
import top.fatweb.api.service.permission.IAuthenticationService
import top.fatweb.api.util.WebUtil
import top.fatweb.api.vo.permission.LoginVo
@@ -26,6 +28,34 @@ import top.fatweb.api.vo.permission.TokenVo
class AuthenticationController(
private val authenticationService: IAuthenticationService
) {
/**
* Register
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Operation(summary = "注册")
@PostMapping("/register")
fun register(@Valid @RequestBody registerParam: RegisterParam): ResponseResult<Nothing> {
authenticationService.register(registerParam)
return ResponseResult.success(ResponseCode.PERMISSION_REGISTER_SUCCESS)
}
/**
* Verify
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Operation(summary = "验证")
@PostMapping("/verify")
fun verify(@Valid @RequestBody verifyParam: VerifyParam): ResponseResult<Nothing> {
authenticationService.verify(verifyParam)
return ResponseResult.success(ResponseCode.PERMISSION_VERIFY_SUCCESS)
}
/**
* Login
*

View File

@@ -74,6 +74,7 @@ object UserConverter {
fun userToUserWithRoleInfoVo(user: User) = UserWithRoleInfoVo(
id = user.id,
username = user.username,
verify = user.verify,
locking = user.locking?.let { it == 1 },
expiration = user.expiration,
credentialsExpiration = user.credentialsExpiration,
@@ -137,6 +138,7 @@ object UserConverter {
id = user.id,
username = user.username,
password = user.password,
verify = user.verify,
locking = user.locking?.let { it == 1 },
expiration = user.expiration,
credentialsExpiration = user.credentialsExpiration,

View File

@@ -18,6 +18,8 @@ enum class ResponseCode(val code: Int) {
PERMISSION_PASSWORD_CHANGE_SUCCESS(BusinessCode.PERMISSION, 1),
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_UNAUTHORIZED(BusinessCode.PERMISSION, 50),
PERMISSION_USERNAME_NOT_FOUND(BusinessCode.PERMISSION, 51),

View File

@@ -46,6 +46,15 @@ class User() : Serializable {
@TableField("password")
var password: String? = null
/**
* Verify
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@TableField("verify")
var verify: String? = null
/**
* Locking
*

View File

@@ -19,7 +19,7 @@ data class LoginParam(
*/
@Schema(description = "账户", example = "test", required = true)
@field:NotBlank(message = "Account can not be blank")
val account: String? = null,
val account: String?,
/**
* Password
@@ -29,5 +29,5 @@ data class LoginParam(
*/
@Schema(description = "密码", example = "test123456", required = true)
@field:NotBlank(message = "Password can not be blank")
val password: String? = null
val password: String?
)

View File

@@ -0,0 +1,34 @@
package top.fatweb.api.param.permission
import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.Email
import jakarta.validation.constraints.NotBlank
/**
* Register parameters
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "注册请求参数")
data class RegisterParam(
/**
* Email
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "邮箱", example = "guest@fatweb.top", required = true)
@field:Email(message = "Illegal email address")
val email: String?,
/**
* Password
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "密码", example = "test123456", required = true)
@field:NotBlank(message = "Password can not be blank")
val password: String?
)

View File

@@ -0,0 +1,50 @@
package top.fatweb.api.param.permission
import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.NotBlank
/**
* Verify parameters
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "验证请求参数")
data class VerifyParam(
/**
* Code
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "验证码", example = "9c4b8199-1dbe-4f6f-96a5-fe1d75cc6a65", required = true)
@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
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "昵称", example = "QwQ")
val nickname: String?,
/**
* Avatar
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "头像")
val avatar: String?
)

View File

@@ -37,5 +37,5 @@ data class GroupAddParam(
* @since 1.0.0
*/
@Schema(description = "角色 ID 列表")
val roleIds: List<Long>? = null
val roleIds: List<Long>?
)

View File

@@ -19,7 +19,7 @@ data class GroupGetParam(
* @since 1.0.0
*/
@Schema(description = "查询用户组名称")
val searchName: String? = null,
val searchName: String?,
/**
* Use regex

View File

@@ -48,5 +48,5 @@ data class GroupUpdateParam(
* @since 1.0.0
*/
@Schema(description = "角色 ID 列表")
val roleIds: List<Long>? = null
val roleIds: List<Long>?
)

View File

@@ -37,5 +37,5 @@ data class RoleAddParam(
* @since 1.0.0
*/
@Schema(description = "权限 ID 列表")
val powerIds: List<Long>? = null
val powerIds: List<Long>?
)

View File

@@ -19,7 +19,7 @@ data class RoleGetParam(
* @since 1.0.0
*/
@Schema(description = "查询角色名称")
val searchName: String? = null,
val searchName: String?,
/**
* Use regex

View File

@@ -48,5 +48,5 @@ data class RoleUpdateParam(
* @since 1.0.0
*/
@Schema(description = "权限 ID 列表")
val powerIds: List<Long>? = null
val powerIds: List<Long>?
)

View File

@@ -32,6 +32,15 @@ data class UserAddParam(
@Schema(description = "密码(为空自动生成随机密码)")
val password: String?,
/**
* Verified
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "是否已验证")
val verified: Boolean = false,
/**
* Locking
*

View File

@@ -28,7 +28,7 @@ data class UserGetParam(
* @since 1.0.0
*/
@Schema(description = "查询内容")
val searchValue: String? = null,
val searchValue: String?,
/**
* Use regex

View File

@@ -32,6 +32,15 @@ data class UserUpdateParam(
@Schema(description = "用户名")
val username: String?,
/**
* Verified
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "是否已验证")
val verified: Boolean = false,
/**
* Locking
*

View File

@@ -21,7 +21,7 @@ data class SysLogGetParam(
* @since 1.0.0
*/
@Schema(description = "类型过滤(多个使用逗号分隔)", example = "INFO", allowableValues = ["INFO", "ERROR"])
val logType: String? = null,
val logType: String?,
/**
* Request method to filter
@@ -34,7 +34,7 @@ data class SysLogGetParam(
example = "GET,POST",
allowableValues = ["GET", "POST", "PUT", "PATCH", "DELETE", "DELETE", "OPTIONS"]
)
val requestMethod: String? = null,
val requestMethod: String?,
/**
* Request URL to search for
@@ -43,7 +43,7 @@ data class SysLogGetParam(
* @since 1.0.0
*/
@Schema(description = "查询请求 Url")
val searchRequestUrl: String? = null,
val searchRequestUrl: String?,
/**
* Use regex
@@ -65,7 +65,7 @@ data class SysLogGetParam(
*/
@Schema(description = "查询开始时间")
@DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
val searchStartTime: LocalDateTime? = null,
val searchStartTime: LocalDateTime?,
/**
* End time to search for
@@ -76,5 +76,5 @@ data class SysLogGetParam(
*/
@Schema(description = "查询结束时间")
@DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
val searchEndTime: LocalDateTime? = null
val searchEndTime: LocalDateTime?
) : PageSortParam()

View File

@@ -11,6 +11,22 @@ import top.fatweb.api.vo.api.v1.avatar.AvatarBase64Vo
* @since 1.0.0
*/
interface IAvatarService {
/**
* Generate random avatar
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
fun random(avatarBaseParam: AvatarBaseParam?): ByteArray
/**
* Generate random avatar as base64
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
fun randomBase64(avatarBaseParam: AvatarBaseParam?): AvatarBase64Vo
/**
* Generate triangle style avatar
*

View File

@@ -25,6 +25,34 @@ import kotlin.io.encoding.ExperimentalEncodingApi
@OptIn(ExperimentalEncodingApi::class)
@Service
class AvatarServiceImpl : IAvatarService {
override fun random(avatarBaseParam: AvatarBaseParam?): ByteArray =
when ((1..4).random()) {
1 -> triangle(avatarBaseParam)
2 -> square(avatarBaseParam)
3 -> identicon(avatarBaseParam)
else -> github(AvatarGitHubParam().apply {
seed = avatarBaseParam?.seed
size = avatarBaseParam?.size
margin = avatarBaseParam?.margin
padding = avatarBaseParam?.padding
colors = avatarBaseParam?.colors
background = avatarBaseParam?.background
})
}
override fun randomBase64(avatarBaseParam: AvatarBaseParam?): AvatarBase64Vo = when ((1..4).random()) {
1 -> triangleBase64(avatarBaseParam)
2 -> squareBase64(avatarBaseParam)
3 -> identiconBase64(avatarBaseParam)
else -> githubBase64(AvatarGitHubParam().apply {
seed = avatarBaseParam?.seed
size = avatarBaseParam?.size
margin = avatarBaseParam?.margin
padding = avatarBaseParam?.padding
colors = avatarBaseParam?.colors
background = avatarBaseParam?.background
})
}
override fun triangle(avatarBaseParam: AvatarBaseParam?): ByteArray {
val avatar = (

View File

@@ -3,6 +3,8 @@ package top.fatweb.api.service.permission
import jakarta.servlet.http.HttpServletRequest
import top.fatweb.api.entity.permission.User
import top.fatweb.api.param.permission.LoginParam
import top.fatweb.api.param.permission.RegisterParam
import top.fatweb.api.param.permission.VerifyParam
import top.fatweb.api.vo.permission.LoginVo
import top.fatweb.api.vo.permission.TokenVo
@@ -13,6 +15,22 @@ import top.fatweb.api.vo.permission.TokenVo
* @since 1.0.0
*/
interface IAuthenticationService {
/**
* Register
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
fun register(registerParam: RegisterParam)
/**
* Verify
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
fun verify(verifyParam: VerifyParam)
/**
* Login
*

View File

@@ -6,15 +6,22 @@ import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import top.fatweb.api.annotation.EventLogRecord
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.TokenHasExpiredException
import top.fatweb.api.param.permission.LoginParam
import top.fatweb.api.param.permission.RegisterParam
import top.fatweb.api.param.permission.VerifyParam
import top.fatweb.api.properties.SecurityProperties
import top.fatweb.api.service.api.v1.IAvatarService
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.RedisUtil
@@ -23,6 +30,7 @@ import top.fatweb.api.vo.permission.LoginVo
import top.fatweb.api.vo.permission.TokenVo
import java.time.LocalDateTime
import java.time.ZoneOffset
import java.util.*
/**
* Authentication service implement
@@ -37,11 +45,33 @@ import java.time.ZoneOffset
@Service
class AuthenticationServiceImpl(
private val authenticationManager: AuthenticationManager,
private val passwordEncoder: PasswordEncoder,
private val redisUtil: RedisUtil,
private val userService: IUserService
private val userService: IUserService,
private val userInfoService: IUserInfoService,
private val avatarService: IAvatarService
) : IAuthenticationService {
private val logger: Logger = LoggerFactory.getLogger(this::class.java)
@Transactional
override fun register(registerParam: RegisterParam) {
val user = User().apply {
username = "\$UNNAMED_${UUID.randomUUID()}"
password = passwordEncoder.encode(registerParam.password)
locking = 0
enable = 1
}
userService.save(user)
userInfoService.save(UserInfo().apply {
userId = user.id
avatar = avatarService.randomBase64(null).base64
email = registerParam.email
})
}
override fun verify(verifyParam: VerifyParam) {
}
@EventLogRecord(EventLog.Event.LOGIN)
override fun login(request: HttpServletRequest, loginParam: LoginParam): LoginVo {
val usernamePasswordAuthenticationToken =

View File

@@ -43,6 +43,15 @@ data class UserWithPasswordRoleInfoVo(
@Schema(description = "密码")
val password: String?,
/**
* Verify
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "验证信息")
val verify: String?,
/**
* Locking
*

View File

@@ -34,6 +34,15 @@ data class UserWithRoleInfoVo(
@Schema(description = "用户名", example = "User")
val username: String?,
/**
* Verify
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "验证信息")
val verify: String?,
/**
* Locking
*