Support login with email
This commit is contained in:
@@ -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)
|
||||
)
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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?,
|
||||
|
||||
/**
|
||||
|
||||
@@ -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?,
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -6,10 +6,11 @@ create table if not exists t_user_info
|
||||
user_id bigint not null comment '用户ID',
|
||||
nickname varchar(50) null comment '昵称',
|
||||
avatar text null comment '头像',
|
||||
email varchar(100) null comment '邮箱',
|
||||
email varchar(100) not null comment '邮箱',
|
||||
create_time datetime not null default (utc_timestamp()) comment '创建时间',
|
||||
update_time datetime not null default (utc_timestamp()) comment '修改时间',
|
||||
deleted bigint not null default 0,
|
||||
version int not null default 0,
|
||||
constraint t_user_info_unique unique (user_id, deleted)
|
||||
constraint t_user_info_unique_user_id unique (user_id, deleted),
|
||||
constraint t_user_info_unique_email unique (email, deleted)
|
||||
) comment '用户资料表';
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="top.fatweb.api.mapper.permission.UserMapper">
|
||||
<select id="selectOneWithPowerInfoByUsername" resultMap="userWithPowerInfoMap">
|
||||
<select id="selectOneWithPowerInfoByAccount" resultMap="userWithPowerInfoMap">
|
||||
select t_user.id as user_id,
|
||||
t_user.username as user_username,
|
||||
t_user.password as user_password,
|
||||
@@ -55,7 +55,7 @@
|
||||
left join t_func as tf on tp.id = tf.id
|
||||
left join t_operation as t on tp.id = t.id
|
||||
where t_user.deleted = 0
|
||||
and t_user.username = #{username};
|
||||
and (tui.email = #{account} or t_user.username = #{account});
|
||||
</select>
|
||||
|
||||
<select id="selectPage" resultType="long">
|
||||
|
||||
Reference in New Issue
Block a user