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 f5acf94..c6f52e0 100644 --- a/src/main/kotlin/top/fatweb/api/controller/permission/AuthenticationController.kt +++ b/src/main/kotlin/top/fatweb/api/controller/permission/AuthenticationController.kt @@ -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) ) /** 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 1d3cb5b..c488e3d 100644 --- a/src/main/kotlin/top/fatweb/api/converter/permission/UserConverter.kt +++ b/src/main/kotlin/top/fatweb/api/converter/permission/UserConverter.kt @@ -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 * diff --git a/src/main/kotlin/top/fatweb/api/mapper/permission/UserMapper.kt b/src/main/kotlin/top/fatweb/api/mapper/permission/UserMapper.kt index 88f3c39..5a3489f 100644 --- a/src/main/kotlin/top/fatweb/api/mapper/permission/UserMapper.kt +++ b/src/main/kotlin/top/fatweb/api/mapper/permission/UserMapper.kt @@ -17,15 +17,15 @@ import top.fatweb.api.entity.permission.User @Mapper interface UserMapper : BaseMapper { /** - * 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 diff --git a/src/main/kotlin/top/fatweb/api/param/permission/LoginParam.kt b/src/main/kotlin/top/fatweb/api/param/permission/LoginParam.kt index b937123..a638d53 100644 --- a/src/main/kotlin/top/fatweb/api/param/permission/LoginParam.kt +++ b/src/main/kotlin/top/fatweb/api/param/permission/LoginParam.kt @@ -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 diff --git a/src/main/kotlin/top/fatweb/api/param/permission/user/UserAddParam.kt b/src/main/kotlin/top/fatweb/api/param/permission/user/UserAddParam.kt index f4fc726..50e7f14 100644 --- a/src/main/kotlin/top/fatweb/api/param/permission/user/UserAddParam.kt +++ b/src/main/kotlin/top/fatweb/api/param/permission/user/UserAddParam.kt @@ -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?, /** diff --git a/src/main/kotlin/top/fatweb/api/param/permission/user/UserUpdateParam.kt b/src/main/kotlin/top/fatweb/api/param/permission/user/UserUpdateParam.kt index 8d9f350..eb76dbe 100644 --- a/src/main/kotlin/top/fatweb/api/param/permission/user/UserUpdateParam.kt +++ b/src/main/kotlin/top/fatweb/api/param/permission/user/UserUpdateParam.kt @@ -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?, /** 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 b6d459b..3ec2c2b 100644 --- a/src/main/kotlin/top/fatweb/api/service/permission/IAuthenticationService.kt +++ b/src/main/kotlin/top/fatweb/api/service/permission/IAuthenticationService.kt @@ -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 diff --git a/src/main/kotlin/top/fatweb/api/service/permission/IUserService.kt b/src/main/kotlin/top/fatweb/api/service/permission/IUserService.kt index 5dc403a..a208420 100644 --- a/src/main/kotlin/top/fatweb/api/service/permission/IUserService.kt +++ b/src/main/kotlin/top/fatweb/api/service/permission/IUserService.kt @@ -19,15 +19,15 @@ import top.fatweb.api.vo.permission.UserWithRoleInfoVo */ interface IUserService : IService { /** - * 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 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 2e4f5cb..c57a22a 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 @@ -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) diff --git a/src/main/kotlin/top/fatweb/api/service/permission/impl/UserDetailsServiceImpl.kt b/src/main/kotlin/top/fatweb/api/service/permission/impl/UserDetailsServiceImpl.kt index a1bce50..f92d344 100644 --- a/src/main/kotlin/top/fatweb/api/service/permission/impl/UserDetailsServiceImpl.kt +++ b/src/main/kotlin/top/fatweb/api/service/permission/impl/UserDetailsServiceImpl.kt @@ -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) diff --git a/src/main/kotlin/top/fatweb/api/service/permission/impl/UserServiceImpl.kt b/src/main/kotlin/top/fatweb/api/service/permission/impl/UserServiceImpl.kt index 3dfa092..f35f537 100644 --- a/src/main/kotlin/top/fatweb/api/service/permission/impl/UserServiceImpl.kt +++ b/src/main/kotlin/top/fatweb/api/service/permission/impl/UserServiceImpl.kt @@ -61,8 +61,8 @@ class UserServiceImpl( private val userRoleService: IUserRoleService, private val userGroupService: IUserGroupService ) : ServiceImpl(), 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 { val userIdsPage = Page(userGetParam?.currentPage ?: 1, userGetParam?.pageSize ?: 20) diff --git a/src/main/resources/db/migration/master/V1_0_0_231104__Add_table_'t_user_info'.sql b/src/main/resources/db/migration/master/V1_0_0_231104__Add_table_'t_user_info'.sql index 0231a70..916e1fa 100644 --- a/src/main/resources/db/migration/master/V1_0_0_231104__Add_table_'t_user_info'.sql +++ b/src/main/resources/db/migration/master/V1_0_0_231104__Add_table_'t_user_info'.sql @@ -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 '用户资料表'; \ No newline at end of file diff --git a/src/main/resources/mapper/permission/UserMapper.xml b/src/main/resources/mapper/permission/UserMapper.xml index cf2ff7c..52587ee 100644 --- a/src/main/resources/mapper/permission/UserMapper.xml +++ b/src/main/resources/mapper/permission/UserMapper.xml @@ -1,7 +1,7 @@ - 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});