diff --git a/src/main/kotlin/top/fatweb/api/controller/permission/UserController.kt b/src/main/kotlin/top/fatweb/api/controller/permission/UserController.kt index 47ce79e..9d22f52 100644 --- a/src/main/kotlin/top/fatweb/api/controller/permission/UserController.kt +++ b/src/main/kotlin/top/fatweb/api/controller/permission/UserController.kt @@ -6,10 +6,8 @@ import jakarta.validation.Valid import org.springframework.web.bind.annotation.* import top.fatweb.api.entity.common.ResponseCode import top.fatweb.api.entity.common.ResponseResult -import top.fatweb.api.param.permission.user.UserAddParam -import top.fatweb.api.param.permission.user.UserDeleteParam -import top.fatweb.api.param.permission.user.UserGetParam -import top.fatweb.api.param.permission.user.UserUpdateParam +import top.fatweb.api.exception.NoRecordFoundException +import top.fatweb.api.param.permission.user.* import top.fatweb.api.service.permission.IUserService import top.fatweb.api.vo.PageVo import top.fatweb.api.vo.permission.UserWithPasswordRoleInfoVo @@ -50,7 +48,7 @@ class UserController( return userService.getOne(id)?.let { ResponseResult.databaseSuccess(data = it) } ?: let { - ResponseResult.databaseFail(ResponseCode.DATABASE_NO_RECORD_FOUND) + throw NoRecordFoundException() } } @@ -74,6 +72,13 @@ class UserController( } ?: let { ResponseResult.databaseFail(ResponseCode.DATABASE_UPDATE_FILED) } } + @Operation(summary = "修改密码") + @PatchMapping + fun changePassword(@Valid @RequestBody userChangePasswordParam: UserChangePasswordParam): ResponseResult { + userService.changePassword(userChangePasswordParam) + return ResponseResult.databaseSuccess(ResponseCode.DATABASE_UPDATE_SUCCESS) + } + @Operation(summary = "删除用户") @DeleteMapping("/{id}") fun delete(@PathVariable id: Long): ResponseResult { diff --git a/src/main/kotlin/top/fatweb/api/exception/NoRecordFoundException.kt b/src/main/kotlin/top/fatweb/api/exception/NoRecordFoundException.kt new file mode 100644 index 0000000..42961fd --- /dev/null +++ b/src/main/kotlin/top/fatweb/api/exception/NoRecordFoundException.kt @@ -0,0 +1,9 @@ +package top.fatweb.api.exception + +/** + * No record found exception + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +class NoRecordFoundException : RuntimeException("No record found") \ 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 ff66574..4e0716b 100644 --- a/src/main/kotlin/top/fatweb/api/handler/ExceptionHandler.kt +++ b/src/main/kotlin/top/fatweb/api/handler/ExceptionHandler.kt @@ -15,6 +15,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.avatargenerator.AvatarException @@ -64,7 +65,11 @@ class ExceptionHandler { is CredentialsExpiredException -> { logger.debug(e.localizedMessage, e) - ResponseResult.fail(ResponseCode.PERMISSION_USER_CREDENTIALS_EXPIRED, "User credentials have expired", null) + ResponseResult.fail( + ResponseCode.PERMISSION_USER_CREDENTIALS_EXPIRED, + "User credentials have expired", + null + ) } is DisabledException -> { @@ -84,7 +89,11 @@ class ExceptionHandler { is BadCredentialsException -> { logger.debug(e.localizedMessage, e) - ResponseResult.fail(ResponseCode.PERMISSION_LOGIN_USERNAME_PASSWORD_ERROR, "Wrong user name or password", null) + ResponseResult.fail( + ResponseCode.PERMISSION_LOGIN_USERNAME_PASSWORD_ERROR, + "Wrong user name or password", + null + ) } is SignatureVerificationException, is JWTDecodeException -> { @@ -107,6 +116,11 @@ class ExceptionHandler { ResponseResult.fail(ResponseCode.DATABASE_DUPLICATE_KEY, "Duplicate key", null) } + is NoRecordFoundException -> { + logger.debug(e.localizedMessage, e) + ResponseResult.fail(ResponseCode.DATABASE_NO_RECORD_FOUND, e.localizedMessage, null) + } + is AvatarException -> { logger.debug(e.localizedMessage, e) ResponseResult.fail(ResponseCode.API_AVATAR_ERROR, e.localizedMessage, null) diff --git a/src/main/kotlin/top/fatweb/api/param/permission/user/UserChangePasswordParam.kt b/src/main/kotlin/top/fatweb/api/param/permission/user/UserChangePasswordParam.kt new file mode 100644 index 0000000..55a1d79 --- /dev/null +++ b/src/main/kotlin/top/fatweb/api/param/permission/user/UserChangePasswordParam.kt @@ -0,0 +1,20 @@ +package top.fatweb.api.param.permission.user + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.NotNull +import java.time.LocalDateTime + +@Schema(description = "用户更改密码请求参数") +data class UserChangePasswordParam( + @Schema(description = "用户 ID") + @field:NotNull(message = "ID can not be null") + val id: Long?, + + @Schema(description = "新密码") + @field:NotBlank(message = "Password can not be blank") + val password: String?, + + @Schema(description = "认证过期时间") + val credentialsExpiration: LocalDateTime? +) 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 3326935..8731b61 100644 --- a/src/main/kotlin/top/fatweb/api/service/permission/IUserService.kt +++ b/src/main/kotlin/top/fatweb/api/service/permission/IUserService.kt @@ -2,10 +2,7 @@ package top.fatweb.api.service.permission import com.baomidou.mybatisplus.extension.service.IService import top.fatweb.api.entity.permission.User -import top.fatweb.api.param.permission.user.UserAddParam -import top.fatweb.api.param.permission.user.UserDeleteParam -import top.fatweb.api.param.permission.user.UserGetParam -import top.fatweb.api.param.permission.user.UserUpdateParam +import top.fatweb.api.param.permission.user.* import top.fatweb.api.vo.PageVo import top.fatweb.api.vo.permission.UserWithInfoVo import top.fatweb.api.vo.permission.UserWithPasswordRoleInfoVo @@ -33,6 +30,8 @@ interface IUserService : IService { fun update(userUpdateParam: UserUpdateParam): UserWithRoleInfoVo? + fun changePassword(userChangePasswordParam: UserChangePasswordParam) + fun deleteOne(id: Long) fun delete(userDeleteParam: UserDeleteParam) 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 cb1b1ef..b09bd1e 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 @@ -1,6 +1,7 @@ package top.fatweb.api.service.permission.impl import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper +import com.baomidou.mybatisplus.extension.kotlin.KtUpdateWrapper import com.baomidou.mybatisplus.extension.plugins.pagination.Page import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl import org.springframework.security.crypto.password.PasswordEncoder @@ -11,11 +12,9 @@ import top.fatweb.api.entity.permission.User import top.fatweb.api.entity.permission.UserGroup import top.fatweb.api.entity.permission.UserInfo import top.fatweb.api.entity.permission.UserRole +import top.fatweb.api.exception.NoRecordFoundException import top.fatweb.api.mapper.permission.UserMapper -import top.fatweb.api.param.permission.user.UserAddParam -import top.fatweb.api.param.permission.user.UserDeleteParam -import top.fatweb.api.param.permission.user.UserGetParam -import top.fatweb.api.param.permission.user.UserUpdateParam +import top.fatweb.api.param.permission.user.* import top.fatweb.api.service.permission.* import top.fatweb.api.util.PageUtil import top.fatweb.api.util.StrUtil @@ -23,6 +22,8 @@ import top.fatweb.api.util.WebUtil import top.fatweb.api.vo.PageVo import top.fatweb.api.vo.permission.UserWithPasswordRoleInfoVo import top.fatweb.api.vo.permission.UserWithRoleInfoVo +import java.time.LocalDateTime +import java.time.ZoneOffset /** * User service implement @@ -120,6 +121,7 @@ class UserServiceImpl( @Transactional override fun update(userUpdateParam: UserUpdateParam): UserWithRoleInfoVo? { val user = UserConverter.userUpdateParamToUser(userUpdateParam) + user.updateTime = LocalDateTime.now(ZoneOffset.UTC) val oldRoleList = userRoleService.list( KtQueryWrapper(UserRole()).select(UserRole::roleId).eq(UserRole::userId, userUpdateParam.id) @@ -193,14 +195,38 @@ class UserServiceImpl( return UserConverter.userToUserWithRoleInfoVo(user) } + override fun changePassword(userChangePasswordParam: UserChangePasswordParam) { + val user = baseMapper.selectById(userChangePasswordParam.id) + user?.let { + val wrapper = KtUpdateWrapper(User()) + wrapper.eq(User::id, user.id) + .set(User::password, passwordEncoder.encode(userChangePasswordParam.password)) + .set(User::credentialsExpiration, userChangePasswordParam.credentialsExpiration) + .set(User::updateTime, LocalDateTime.now(ZoneOffset.UTC)) + + this.update(wrapper) + } ?: let { + throw NoRecordFoundException() + } + } + override fun deleteOne(id: Long) { + if (id == 0L) { + return + } + this.delete(UserDeleteParam(listOf(id))) } override fun delete(userDeleteParam: UserDeleteParam) { - baseMapper.deleteBatchIds(userDeleteParam.ids) - userInfoService.remove(KtQueryWrapper(UserInfo()).`in`(UserInfo::userId, userDeleteParam.ids)) - userRoleService.remove(KtQueryWrapper(UserRole()).`in`(UserRole::userId, userDeleteParam.ids)) - userGroupService.remove(KtQueryWrapper(UserGroup()).`in`(UserGroup::userId, userDeleteParam.ids)) + val ids = userDeleteParam.ids.filter { it != 0L } + if (ids.isEmpty()) { + return + } + + baseMapper.deleteBatchIds(ids) + userInfoService.remove(KtQueryWrapper(UserInfo()).`in`(UserInfo::userId, ids)) + userRoleService.remove(KtQueryWrapper(UserRole()).`in`(UserRole::userId, ids)) + userGroupService.remove(KtQueryWrapper(UserGroup()).`in`(UserGroup::userId, ids)) } }