Support login with email

This commit is contained in:
2023-12-20 14:55:30 +08:00
parent 60353906ad
commit e7c8311b83
13 changed files with 34 additions and 43 deletions

View File

@@ -7,7 +7,6 @@ import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import top.fatweb.api.annotation.BaseController
import top.fatweb.api.converter.permission.UserConverter
import top.fatweb.api.entity.common.ResponseCode
import top.fatweb.api.entity.common.ResponseResult
import top.fatweb.api.param.permission.LoginParam
@@ -46,7 +45,7 @@ class AuthenticationController(
ResponseResult.success(
ResponseCode.PERMISSION_LOGIN_SUCCESS,
"Login success",
authenticationService.login(request, UserConverter.loginParamToUser(loginParam))
authenticationService.login(request, loginParam)
)
/**

View File

@@ -5,7 +5,6 @@ import top.fatweb.api.entity.permission.Group
import top.fatweb.api.entity.permission.Role
import top.fatweb.api.entity.permission.User
import top.fatweb.api.entity.permission.UserInfo
import top.fatweb.api.param.permission.LoginParam
import top.fatweb.api.param.permission.user.UserAddParam
import top.fatweb.api.param.permission.user.UserUpdateParam
import top.fatweb.api.vo.PageVo
@@ -22,21 +21,6 @@ import top.fatweb.avatargenerator.GitHubAvatar
* @since 1.0.0
*/
object UserConverter {
/**
* Convert LoginParam object into User object
*
* @param loginParam LoginParam object
* @return User object
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see LoginParam
* @see User
*/
fun loginParamToUser(loginParam: LoginParam) = User().apply {
username = loginParam.username
password = loginParam.password
}
/**
* Convert User object into UserWithPowerInfoVo object
*

View File

@@ -17,15 +17,15 @@ import top.fatweb.api.entity.permission.User
@Mapper
interface UserMapper : BaseMapper<User> {
/**
* Select one user with power and information by username
* Select one user with power and information by username or email
*
* @param username Username
* @param account Username or email
* @return User object with power and information
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see User
*/
fun selectOneWithPowerInfoByUsername(@Param("username") username: String): User?
fun selectOneWithPowerInfoByAccount(@Param("account") account: String): User?
/**
* Select user in page

View File

@@ -12,14 +12,14 @@ import jakarta.validation.constraints.NotBlank
@Schema(description = "登录请求参数")
data class LoginParam(
/**
* Username
* Account
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "用户名", example = "test", required = true)
@field:NotBlank(message = "Username can not be blank")
val username: String? = null,
@Schema(description = "账户", example = "test", required = true)
@field:NotBlank(message = "Account can not be blank")
val account: String? = null,
/**
* Password

View File

@@ -2,6 +2,7 @@ package top.fatweb.api.param.permission.user
import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.NotBlank
import jakarta.validation.constraints.Pattern
import java.time.LocalDateTime
/**
@@ -94,6 +95,7 @@ data class UserAddParam(
* @since 1.0.0
*/
@Schema(description = "邮箱")
@Pattern(regexp = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*\$", message = "Illegal email address")
val email: String?,
/**

View File

@@ -2,6 +2,7 @@ package top.fatweb.api.param.permission.user
import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.NotNull
import jakarta.validation.constraints.Pattern
import java.time.LocalDateTime
/**
@@ -94,6 +95,7 @@ data class UserUpdateParam(
* @since 1.0.0
*/
@Schema(description = "邮箱")
@Pattern(regexp = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*\$", message = "Illegal email address")
val email: String?,
/**

View File

@@ -2,6 +2,7 @@ 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.vo.permission.LoginVo
import top.fatweb.api.vo.permission.TokenVo
@@ -16,7 +17,7 @@ interface IAuthenticationService {
* Login
*
* @param request
* @param user User object
* @param loginParam Login parameters
* @return LoginVo object
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
@@ -24,7 +25,7 @@ interface IAuthenticationService {
* @see User
* @see LoginVo
*/
fun login(request: HttpServletRequest, user: User): LoginVo
fun login(request: HttpServletRequest, loginParam: LoginParam): LoginVo
/**
* Logout

View File

@@ -19,15 +19,15 @@ import top.fatweb.api.vo.permission.UserWithRoleInfoVo
*/
interface IUserService : IService<User> {
/**
* Get user with power by username
* Get user with power by username or email
*
* @param username Username
* @param account Username or email
* @return User object
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see User
*/
fun getUserWithPowerByUsername(username: String): User?
fun getUserWithPowerByAccount(account: String): User?
/**
* Get user information

View File

@@ -12,6 +12,7 @@ import top.fatweb.api.entity.permission.LoginUser
import top.fatweb.api.entity.permission.User
import top.fatweb.api.entity.system.EventLog
import top.fatweb.api.exception.TokenHasExpiredException
import top.fatweb.api.param.permission.LoginParam
import top.fatweb.api.properties.SecurityProperties
import top.fatweb.api.service.permission.IAuthenticationService
import top.fatweb.api.service.permission.IUserService
@@ -42,8 +43,9 @@ class AuthenticationServiceImpl(
private val logger: Logger = LoggerFactory.getLogger(this::class.java)
@EventLogRecord(EventLog.Event.LOGIN)
override fun login(request: HttpServletRequest, user: User): LoginVo {
val usernamePasswordAuthenticationToken = UsernamePasswordAuthenticationToken(user.username, user.password)
override fun login(request: HttpServletRequest, loginParam: LoginParam): LoginVo {
val usernamePasswordAuthenticationToken =
UsernamePasswordAuthenticationToken(loginParam.account, loginParam.password)
val authentication = authenticationManager.authenticate(usernamePasswordAuthenticationToken)
authentication ?: let {
throw RuntimeException("Login failed")
@@ -52,13 +54,13 @@ class AuthenticationServiceImpl(
val loginUser = authentication.principal as LoginUser
loginUser.user.password = ""
logger.info("用户登录 [用户名: '{}', IP: '{}']", user.username, request.remoteAddr)
logger.info("用户登录 [用户名: '{}', IP: '{}']", loginUser.username, request.remoteAddr)
userService.update(User().apply {
currentLoginIp = request.remoteAddr
currentLoginTime = LocalDateTime.now(ZoneOffset.UTC)
lastLoginIp = loginUser.user.currentLoginIp
lastLoginTime = loginUser.user.currentLoginTime
}, KtUpdateWrapper(User()).eq(User::username, user.username))
}, KtUpdateWrapper(User()).eq(User::username, loginUser.username))
val userId = loginUser.user.id.toString()
val jwt = JwtUtil.createJwt(userId)

View File

@@ -16,8 +16,8 @@ import top.fatweb.api.service.permission.IUserService
*/
@Service
class UserDetailsServiceImpl(val userService: IUserService) : UserDetailsService {
override fun loadUserByUsername(username: String): UserDetails {
val user = userService.getUserWithPowerByUsername(username)
override fun loadUserByUsername(account: String): UserDetails {
val user = userService.getUserWithPowerByAccount(account)
user ?: let { throw Exception("Username not found") }
return LoginUser(user)

View File

@@ -61,8 +61,8 @@ class UserServiceImpl(
private val userRoleService: IUserRoleService,
private val userGroupService: IUserGroupService
) : ServiceImpl<UserMapper, User>(), IUserService {
override fun getUserWithPowerByUsername(username: String): User? {
val user = baseMapper.selectOneWithPowerInfoByUsername(username)
override fun getUserWithPowerByAccount(account: String): User? {
val user = baseMapper.selectOneWithPowerInfoByAccount(account)
user ?: let { return null }
if (user.id == 0L) {
@@ -76,7 +76,7 @@ class UserServiceImpl(
}
override fun getInfo() = WebUtil.getLoginUsername()
?.let { username -> getUserWithPowerByUsername(username)?.let { UserConverter.userToUserWithPowerInfoVo(it) } }
?.let { username -> getUserWithPowerByAccount(username)?.let { UserConverter.userToUserWithPowerInfoVo(it) } }
override fun getPage(userGetParam: UserGetParam?): PageVo<UserWithRoleInfoVo> {
val userIdsPage = Page<Long>(userGetParam?.currentPage ?: 1, userGetParam?.pageSize ?: 20)